Upload 343 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +4 -0
- ComfyUI/app/__init__.py +0 -0
- ComfyUI/app/__pycache__/__init__.cpython-310.pyc +0 -0
- ComfyUI/app/__pycache__/app_settings.cpython-310.pyc +0 -0
- ComfyUI/app/__pycache__/frontend_management.cpython-310.pyc +0 -0
- ComfyUI/app/__pycache__/user_manager.cpython-310.pyc +0 -0
- ComfyUI/app/app_settings.py +54 -0
- ComfyUI/app/frontend_management.py +188 -0
- ComfyUI/app/user_manager.py +205 -0
- ComfyUI/comfy/__pycache__/checkpoint_pickle.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/checkpoint_pickle.cpython-39.pyc +0 -0
- ComfyUI/comfy/__pycache__/cli_args.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/cli_args.cpython-39.pyc +0 -0
- ComfyUI/comfy/__pycache__/clip_model.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/clip_model.cpython-39.pyc +0 -0
- ComfyUI/comfy/__pycache__/clip_vision.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/clip_vision.cpython-39.pyc +0 -0
- ComfyUI/comfy/__pycache__/conds.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/controlnet.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/diffusers_convert.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/diffusers_load.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/diffusers_load.cpython-39.pyc +0 -0
- ComfyUI/comfy/__pycache__/gligen.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/latent_formats.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/lora.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/model_base.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/model_detection.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/model_management.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/model_management.cpython-39.pyc +0 -0
- ComfyUI/comfy/__pycache__/model_patcher.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/model_patcher.cpython-39.pyc +0 -0
- ComfyUI/comfy/__pycache__/model_sampling.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/ops.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/ops.cpython-39.pyc +0 -0
- ComfyUI/comfy/__pycache__/options.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/options.cpython-39.pyc +0 -0
- ComfyUI/comfy/__pycache__/sa_t5.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/sample.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/sampler_helpers.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/samplers.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/sd.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/sd.cpython-39.pyc +0 -0
- ComfyUI/comfy/__pycache__/sd1_clip.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/sd2_clip.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/sd3_clip.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/sdxl_clip.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/supported_models.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/supported_models_base.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/t5.cpython-310.pyc +0 -0
- ComfyUI/comfy/__pycache__/types.cpython-310.pyc +0 -0
.gitattributes
CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
ComfyUI/output/ComfyUI_00001_.png filter=lfs diff=lfs merge=lfs -text
|
37 |
+
ComfyUI/output/ComfyUI_00002_.png filter=lfs diff=lfs merge=lfs -text
|
38 |
+
ComfyUI/temp/ComfyUI_temp_zprxs_00001_.png filter=lfs diff=lfs merge=lfs -text
|
39 |
+
ComfyUI/temp/ComfyUI_temp_zprxs_00002_.png filter=lfs diff=lfs merge=lfs -text
|
ComfyUI/app/__init__.py
ADDED
File without changes
|
ComfyUI/app/__pycache__/__init__.cpython-310.pyc
ADDED
Binary file (148 Bytes). View file
|
|
ComfyUI/app/__pycache__/app_settings.cpython-310.pyc
ADDED
Binary file (2.41 kB). View file
|
|
ComfyUI/app/__pycache__/frontend_management.cpython-310.pyc
ADDED
Binary file (6.21 kB). View file
|
|
ComfyUI/app/__pycache__/user_manager.cpython-310.pyc
ADDED
Binary file (6.31 kB). View file
|
|
ComfyUI/app/app_settings.py
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
from aiohttp import web
|
4 |
+
|
5 |
+
|
6 |
+
class AppSettings():
|
7 |
+
def __init__(self, user_manager):
|
8 |
+
self.user_manager = user_manager
|
9 |
+
|
10 |
+
def get_settings(self, request):
|
11 |
+
file = self.user_manager.get_request_user_filepath(
|
12 |
+
request, "comfy.settings.json")
|
13 |
+
if os.path.isfile(file):
|
14 |
+
with open(file) as f:
|
15 |
+
return json.load(f)
|
16 |
+
else:
|
17 |
+
return {}
|
18 |
+
|
19 |
+
def save_settings(self, request, settings):
|
20 |
+
file = self.user_manager.get_request_user_filepath(
|
21 |
+
request, "comfy.settings.json")
|
22 |
+
with open(file, "w") as f:
|
23 |
+
f.write(json.dumps(settings, indent=4))
|
24 |
+
|
25 |
+
def add_routes(self, routes):
|
26 |
+
@routes.get("/settings")
|
27 |
+
async def get_settings(request):
|
28 |
+
return web.json_response(self.get_settings(request))
|
29 |
+
|
30 |
+
@routes.get("/settings/{id}")
|
31 |
+
async def get_setting(request):
|
32 |
+
value = None
|
33 |
+
settings = self.get_settings(request)
|
34 |
+
setting_id = request.match_info.get("id", None)
|
35 |
+
if setting_id and setting_id in settings:
|
36 |
+
value = settings[setting_id]
|
37 |
+
return web.json_response(value)
|
38 |
+
|
39 |
+
@routes.post("/settings")
|
40 |
+
async def post_settings(request):
|
41 |
+
settings = self.get_settings(request)
|
42 |
+
new_settings = await request.json()
|
43 |
+
self.save_settings(request, {**settings, **new_settings})
|
44 |
+
return web.Response(status=200)
|
45 |
+
|
46 |
+
@routes.post("/settings/{id}")
|
47 |
+
async def post_setting(request):
|
48 |
+
setting_id = request.match_info.get("id", None)
|
49 |
+
if not setting_id:
|
50 |
+
return web.Response(status=400)
|
51 |
+
settings = self.get_settings(request)
|
52 |
+
settings[setting_id] = await request.json()
|
53 |
+
self.save_settings(request, settings)
|
54 |
+
return web.Response(status=200)
|
ComfyUI/app/frontend_management.py
ADDED
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import annotations
|
2 |
+
import argparse
|
3 |
+
import logging
|
4 |
+
import os
|
5 |
+
import re
|
6 |
+
import tempfile
|
7 |
+
import zipfile
|
8 |
+
from dataclasses import dataclass
|
9 |
+
from functools import cached_property
|
10 |
+
from pathlib import Path
|
11 |
+
from typing import TypedDict
|
12 |
+
|
13 |
+
import requests
|
14 |
+
from typing_extensions import NotRequired
|
15 |
+
from comfy.cli_args import DEFAULT_VERSION_STRING
|
16 |
+
|
17 |
+
|
18 |
+
REQUEST_TIMEOUT = 10 # seconds
|
19 |
+
|
20 |
+
|
21 |
+
class Asset(TypedDict):
|
22 |
+
url: str
|
23 |
+
|
24 |
+
|
25 |
+
class Release(TypedDict):
|
26 |
+
id: int
|
27 |
+
tag_name: str
|
28 |
+
name: str
|
29 |
+
prerelease: bool
|
30 |
+
created_at: str
|
31 |
+
published_at: str
|
32 |
+
body: str
|
33 |
+
assets: NotRequired[list[Asset]]
|
34 |
+
|
35 |
+
|
36 |
+
@dataclass
|
37 |
+
class FrontEndProvider:
|
38 |
+
owner: str
|
39 |
+
repo: str
|
40 |
+
|
41 |
+
@property
|
42 |
+
def folder_name(self) -> str:
|
43 |
+
return f"{self.owner}_{self.repo}"
|
44 |
+
|
45 |
+
@property
|
46 |
+
def release_url(self) -> str:
|
47 |
+
return f"https://api.github.com/repos/{self.owner}/{self.repo}/releases"
|
48 |
+
|
49 |
+
@cached_property
|
50 |
+
def all_releases(self) -> list[Release]:
|
51 |
+
releases = []
|
52 |
+
api_url = self.release_url
|
53 |
+
while api_url:
|
54 |
+
response = requests.get(api_url, timeout=REQUEST_TIMEOUT)
|
55 |
+
response.raise_for_status() # Raises an HTTPError if the response was an error
|
56 |
+
releases.extend(response.json())
|
57 |
+
# GitHub uses the Link header to provide pagination links. Check if it exists and update api_url accordingly.
|
58 |
+
if "next" in response.links:
|
59 |
+
api_url = response.links["next"]["url"]
|
60 |
+
else:
|
61 |
+
api_url = None
|
62 |
+
return releases
|
63 |
+
|
64 |
+
@cached_property
|
65 |
+
def latest_release(self) -> Release:
|
66 |
+
latest_release_url = f"{self.release_url}/latest"
|
67 |
+
response = requests.get(latest_release_url, timeout=REQUEST_TIMEOUT)
|
68 |
+
response.raise_for_status() # Raises an HTTPError if the response was an error
|
69 |
+
return response.json()
|
70 |
+
|
71 |
+
def get_release(self, version: str) -> Release:
|
72 |
+
if version == "latest":
|
73 |
+
return self.latest_release
|
74 |
+
else:
|
75 |
+
for release in self.all_releases:
|
76 |
+
if release["tag_name"] in [version, f"v{version}"]:
|
77 |
+
return release
|
78 |
+
raise ValueError(f"Version {version} not found in releases")
|
79 |
+
|
80 |
+
|
81 |
+
def download_release_asset_zip(release: Release, destination_path: str) -> None:
|
82 |
+
"""Download dist.zip from github release."""
|
83 |
+
asset_url = None
|
84 |
+
for asset in release.get("assets", []):
|
85 |
+
if asset["name"] == "dist.zip":
|
86 |
+
asset_url = asset["url"]
|
87 |
+
break
|
88 |
+
|
89 |
+
if not asset_url:
|
90 |
+
raise ValueError("dist.zip not found in the release assets")
|
91 |
+
|
92 |
+
# Use a temporary file to download the zip content
|
93 |
+
with tempfile.TemporaryFile() as tmp_file:
|
94 |
+
headers = {"Accept": "application/octet-stream"}
|
95 |
+
response = requests.get(
|
96 |
+
asset_url, headers=headers, allow_redirects=True, timeout=REQUEST_TIMEOUT
|
97 |
+
)
|
98 |
+
response.raise_for_status() # Ensure we got a successful response
|
99 |
+
|
100 |
+
# Write the content to the temporary file
|
101 |
+
tmp_file.write(response.content)
|
102 |
+
|
103 |
+
# Go back to the beginning of the temporary file
|
104 |
+
tmp_file.seek(0)
|
105 |
+
|
106 |
+
# Extract the zip file content to the destination path
|
107 |
+
with zipfile.ZipFile(tmp_file, "r") as zip_ref:
|
108 |
+
zip_ref.extractall(destination_path)
|
109 |
+
|
110 |
+
|
111 |
+
class FrontendManager:
|
112 |
+
DEFAULT_FRONTEND_PATH = str(Path(__file__).parents[1] / "web")
|
113 |
+
CUSTOM_FRONTENDS_ROOT = str(Path(__file__).parents[1] / "web_custom_versions")
|
114 |
+
|
115 |
+
@classmethod
|
116 |
+
def parse_version_string(cls, value: str) -> tuple[str, str, str]:
|
117 |
+
"""
|
118 |
+
Args:
|
119 |
+
value (str): The version string to parse.
|
120 |
+
|
121 |
+
Returns:
|
122 |
+
tuple[str, str]: A tuple containing provider name and version.
|
123 |
+
|
124 |
+
Raises:
|
125 |
+
argparse.ArgumentTypeError: If the version string is invalid.
|
126 |
+
"""
|
127 |
+
VERSION_PATTERN = r"^([a-zA-Z0-9][a-zA-Z0-9-]{0,38})/([a-zA-Z0-9_.-]+)@(v?\d+\.\d+\.\d+|latest)$"
|
128 |
+
match_result = re.match(VERSION_PATTERN, value)
|
129 |
+
if match_result is None:
|
130 |
+
raise argparse.ArgumentTypeError(f"Invalid version string: {value}")
|
131 |
+
|
132 |
+
return match_result.group(1), match_result.group(2), match_result.group(3)
|
133 |
+
|
134 |
+
@classmethod
|
135 |
+
def init_frontend_unsafe(cls, version_string: str) -> str:
|
136 |
+
"""
|
137 |
+
Initializes the frontend for the specified version.
|
138 |
+
|
139 |
+
Args:
|
140 |
+
version_string (str): The version string.
|
141 |
+
|
142 |
+
Returns:
|
143 |
+
str: The path to the initialized frontend.
|
144 |
+
|
145 |
+
Raises:
|
146 |
+
Exception: If there is an error during the initialization process.
|
147 |
+
main error source might be request timeout or invalid URL.
|
148 |
+
"""
|
149 |
+
if version_string == DEFAULT_VERSION_STRING:
|
150 |
+
return cls.DEFAULT_FRONTEND_PATH
|
151 |
+
|
152 |
+
repo_owner, repo_name, version = cls.parse_version_string(version_string)
|
153 |
+
provider = FrontEndProvider(repo_owner, repo_name)
|
154 |
+
release = provider.get_release(version)
|
155 |
+
|
156 |
+
semantic_version = release["tag_name"].lstrip("v")
|
157 |
+
web_root = str(
|
158 |
+
Path(cls.CUSTOM_FRONTENDS_ROOT) / provider.folder_name / semantic_version
|
159 |
+
)
|
160 |
+
if not os.path.exists(web_root):
|
161 |
+
os.makedirs(web_root, exist_ok=True)
|
162 |
+
logging.info(
|
163 |
+
"Downloading frontend(%s) version(%s) to (%s)",
|
164 |
+
provider.folder_name,
|
165 |
+
semantic_version,
|
166 |
+
web_root,
|
167 |
+
)
|
168 |
+
logging.debug(release)
|
169 |
+
download_release_asset_zip(release, destination_path=web_root)
|
170 |
+
return web_root
|
171 |
+
|
172 |
+
@classmethod
|
173 |
+
def init_frontend(cls, version_string: str) -> str:
|
174 |
+
"""
|
175 |
+
Initializes the frontend with the specified version string.
|
176 |
+
|
177 |
+
Args:
|
178 |
+
version_string (str): The version string to initialize the frontend with.
|
179 |
+
|
180 |
+
Returns:
|
181 |
+
str: The path of the initialized frontend.
|
182 |
+
"""
|
183 |
+
try:
|
184 |
+
return cls.init_frontend_unsafe(version_string)
|
185 |
+
except Exception as e:
|
186 |
+
logging.error("Failed to initialize frontend: %s", e)
|
187 |
+
logging.info("Falling back to the default frontend.")
|
188 |
+
return cls.DEFAULT_FRONTEND_PATH
|
ComfyUI/app/user_manager.py
ADDED
@@ -0,0 +1,205 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
import os
|
3 |
+
import re
|
4 |
+
import uuid
|
5 |
+
import glob
|
6 |
+
import shutil
|
7 |
+
from aiohttp import web
|
8 |
+
from comfy.cli_args import args
|
9 |
+
from folder_paths import user_directory
|
10 |
+
from .app_settings import AppSettings
|
11 |
+
|
12 |
+
default_user = "default"
|
13 |
+
users_file = os.path.join(user_directory, "users.json")
|
14 |
+
|
15 |
+
|
16 |
+
class UserManager():
|
17 |
+
def __init__(self):
|
18 |
+
global user_directory
|
19 |
+
|
20 |
+
self.settings = AppSettings(self)
|
21 |
+
if not os.path.exists(user_directory):
|
22 |
+
os.mkdir(user_directory)
|
23 |
+
if not args.multi_user:
|
24 |
+
print("****** User settings have been changed to be stored on the server instead of browser storage. ******")
|
25 |
+
print("****** For multi-user setups add the --multi-user CLI argument to enable multiple user profiles. ******")
|
26 |
+
|
27 |
+
if args.multi_user:
|
28 |
+
if os.path.isfile(users_file):
|
29 |
+
with open(users_file) as f:
|
30 |
+
self.users = json.load(f)
|
31 |
+
else:
|
32 |
+
self.users = {}
|
33 |
+
else:
|
34 |
+
self.users = {"default": "default"}
|
35 |
+
|
36 |
+
def get_request_user_id(self, request):
|
37 |
+
user = "default"
|
38 |
+
if args.multi_user and "comfy-user" in request.headers:
|
39 |
+
user = request.headers["comfy-user"]
|
40 |
+
|
41 |
+
if user not in self.users:
|
42 |
+
raise KeyError("Unknown user: " + user)
|
43 |
+
|
44 |
+
return user
|
45 |
+
|
46 |
+
def get_request_user_filepath(self, request, file, type="userdata", create_dir=True):
|
47 |
+
global user_directory
|
48 |
+
|
49 |
+
if type == "userdata":
|
50 |
+
root_dir = user_directory
|
51 |
+
else:
|
52 |
+
raise KeyError("Unknown filepath type:" + type)
|
53 |
+
|
54 |
+
user = self.get_request_user_id(request)
|
55 |
+
path = user_root = os.path.abspath(os.path.join(root_dir, user))
|
56 |
+
|
57 |
+
# prevent leaving /{type}
|
58 |
+
if os.path.commonpath((root_dir, user_root)) != root_dir:
|
59 |
+
return None
|
60 |
+
|
61 |
+
if file is not None:
|
62 |
+
# prevent leaving /{type}/{user}
|
63 |
+
path = os.path.abspath(os.path.join(user_root, file))
|
64 |
+
if os.path.commonpath((user_root, path)) != user_root:
|
65 |
+
return None
|
66 |
+
|
67 |
+
parent = os.path.split(path)[0]
|
68 |
+
|
69 |
+
if create_dir and not os.path.exists(parent):
|
70 |
+
os.makedirs(parent, exist_ok=True)
|
71 |
+
|
72 |
+
return path
|
73 |
+
|
74 |
+
def add_user(self, name):
|
75 |
+
name = name.strip()
|
76 |
+
if not name:
|
77 |
+
raise ValueError("username not provided")
|
78 |
+
user_id = re.sub("[^a-zA-Z0-9-_]+", '-', name)
|
79 |
+
user_id = user_id + "_" + str(uuid.uuid4())
|
80 |
+
|
81 |
+
self.users[user_id] = name
|
82 |
+
|
83 |
+
global users_file
|
84 |
+
with open(users_file, "w") as f:
|
85 |
+
json.dump(self.users, f)
|
86 |
+
|
87 |
+
return user_id
|
88 |
+
|
89 |
+
def add_routes(self, routes):
|
90 |
+
self.settings.add_routes(routes)
|
91 |
+
|
92 |
+
@routes.get("/users")
|
93 |
+
async def get_users(request):
|
94 |
+
if args.multi_user:
|
95 |
+
return web.json_response({"storage": "server", "users": self.users})
|
96 |
+
else:
|
97 |
+
user_dir = self.get_request_user_filepath(request, None, create_dir=False)
|
98 |
+
return web.json_response({
|
99 |
+
"storage": "server",
|
100 |
+
"migrated": os.path.exists(user_dir)
|
101 |
+
})
|
102 |
+
|
103 |
+
@routes.post("/users")
|
104 |
+
async def post_users(request):
|
105 |
+
body = await request.json()
|
106 |
+
username = body["username"]
|
107 |
+
if username in self.users.values():
|
108 |
+
return web.json_response({"error": "Duplicate username."}, status=400)
|
109 |
+
|
110 |
+
user_id = self.add_user(username)
|
111 |
+
return web.json_response(user_id)
|
112 |
+
|
113 |
+
@routes.get("/userdata")
|
114 |
+
async def listuserdata(request):
|
115 |
+
directory = request.rel_url.query.get('dir', '')
|
116 |
+
if not directory:
|
117 |
+
return web.Response(status=400)
|
118 |
+
|
119 |
+
path = self.get_request_user_filepath(request, directory)
|
120 |
+
if not path:
|
121 |
+
return web.Response(status=403)
|
122 |
+
|
123 |
+
if not os.path.exists(path):
|
124 |
+
return web.Response(status=404)
|
125 |
+
|
126 |
+
recurse = request.rel_url.query.get('recurse', '').lower() == "true"
|
127 |
+
results = glob.glob(os.path.join(
|
128 |
+
glob.escape(path), '**/*'), recursive=recurse)
|
129 |
+
results = [os.path.relpath(x, path) for x in results if os.path.isfile(x)]
|
130 |
+
|
131 |
+
split_path = request.rel_url.query.get('split', '').lower() == "true"
|
132 |
+
if split_path:
|
133 |
+
results = [[x] + x.split(os.sep) for x in results]
|
134 |
+
|
135 |
+
return web.json_response(results)
|
136 |
+
|
137 |
+
def get_user_data_path(request, check_exists = False, param = "file"):
|
138 |
+
file = request.match_info.get(param, None)
|
139 |
+
if not file:
|
140 |
+
return web.Response(status=400)
|
141 |
+
|
142 |
+
path = self.get_request_user_filepath(request, file)
|
143 |
+
if not path:
|
144 |
+
return web.Response(status=403)
|
145 |
+
|
146 |
+
if check_exists and not os.path.exists(path):
|
147 |
+
return web.Response(status=404)
|
148 |
+
|
149 |
+
return path
|
150 |
+
|
151 |
+
@routes.get("/userdata/{file}")
|
152 |
+
async def getuserdata(request):
|
153 |
+
path = get_user_data_path(request, check_exists=True)
|
154 |
+
if not isinstance(path, str):
|
155 |
+
return path
|
156 |
+
|
157 |
+
return web.FileResponse(path)
|
158 |
+
|
159 |
+
@routes.post("/userdata/{file}")
|
160 |
+
async def post_userdata(request):
|
161 |
+
path = get_user_data_path(request)
|
162 |
+
if not isinstance(path, str):
|
163 |
+
return path
|
164 |
+
|
165 |
+
overwrite = request.query["overwrite"] != "false"
|
166 |
+
if not overwrite and os.path.exists(path):
|
167 |
+
return web.Response(status=409)
|
168 |
+
|
169 |
+
body = await request.read()
|
170 |
+
|
171 |
+
with open(path, "wb") as f:
|
172 |
+
f.write(body)
|
173 |
+
|
174 |
+
resp = os.path.relpath(path, self.get_request_user_filepath(request, None))
|
175 |
+
return web.json_response(resp)
|
176 |
+
|
177 |
+
@routes.delete("/userdata/{file}")
|
178 |
+
async def delete_userdata(request):
|
179 |
+
path = get_user_data_path(request, check_exists=True)
|
180 |
+
if not isinstance(path, str):
|
181 |
+
return path
|
182 |
+
|
183 |
+
os.remove(path)
|
184 |
+
|
185 |
+
return web.Response(status=204)
|
186 |
+
|
187 |
+
@routes.post("/userdata/{file}/move/{dest}")
|
188 |
+
async def move_userdata(request):
|
189 |
+
source = get_user_data_path(request, check_exists=True)
|
190 |
+
if not isinstance(source, str):
|
191 |
+
return source
|
192 |
+
|
193 |
+
dest = get_user_data_path(request, check_exists=False, param="dest")
|
194 |
+
if not isinstance(source, str):
|
195 |
+
return dest
|
196 |
+
|
197 |
+
overwrite = request.query["overwrite"] != "false"
|
198 |
+
if not overwrite and os.path.exists(dest):
|
199 |
+
return web.Response(status=409)
|
200 |
+
|
201 |
+
print(f"moving '{source}' -> '{dest}'")
|
202 |
+
shutil.move(source, dest)
|
203 |
+
|
204 |
+
resp = os.path.relpath(dest, self.get_request_user_filepath(request, None))
|
205 |
+
return web.json_response(resp)
|
ComfyUI/comfy/__pycache__/checkpoint_pickle.cpython-310.pyc
ADDED
Binary file (724 Bytes). View file
|
|
ComfyUI/comfy/__pycache__/checkpoint_pickle.cpython-39.pyc
ADDED
Binary file (720 Bytes). View file
|
|
ComfyUI/comfy/__pycache__/cli_args.cpython-310.pyc
ADDED
Binary file (8.73 kB). View file
|
|
ComfyUI/comfy/__pycache__/cli_args.cpython-39.pyc
ADDED
Binary file (7.43 kB). View file
|
|
ComfyUI/comfy/__pycache__/clip_model.cpython-310.pyc
ADDED
Binary file (8.89 kB). View file
|
|
ComfyUI/comfy/__pycache__/clip_model.cpython-39.pyc
ADDED
Binary file (8.8 kB). View file
|
|
ComfyUI/comfy/__pycache__/clip_vision.cpython-310.pyc
ADDED
Binary file (5.38 kB). View file
|
|
ComfyUI/comfy/__pycache__/clip_vision.cpython-39.pyc
ADDED
Binary file (5.2 kB). View file
|
|
ComfyUI/comfy/__pycache__/conds.cpython-310.pyc
ADDED
Binary file (3.29 kB). View file
|
|
ComfyUI/comfy/__pycache__/controlnet.cpython-310.pyc
ADDED
Binary file (18.6 kB). View file
|
|
ComfyUI/comfy/__pycache__/diffusers_convert.cpython-310.pyc
ADDED
Binary file (7.2 kB). View file
|
|
ComfyUI/comfy/__pycache__/diffusers_load.cpython-310.pyc
ADDED
Binary file (1.32 kB). View file
|
|
ComfyUI/comfy/__pycache__/diffusers_load.cpython-39.pyc
ADDED
Binary file (1.32 kB). View file
|
|
ComfyUI/comfy/__pycache__/gligen.cpython-310.pyc
ADDED
Binary file (10.3 kB). View file
|
|
ComfyUI/comfy/__pycache__/latent_formats.cpython-310.pyc
ADDED
Binary file (5.51 kB). View file
|
|
ComfyUI/comfy/__pycache__/lora.cpython-310.pyc
ADDED
Binary file (6.46 kB). View file
|
|
ComfyUI/comfy/__pycache__/model_base.cpython-310.pyc
ADDED
Binary file (23.9 kB). View file
|
|
ComfyUI/comfy/__pycache__/model_detection.cpython-310.pyc
ADDED
Binary file (15.4 kB). View file
|
|
ComfyUI/comfy/__pycache__/model_management.cpython-310.pyc
ADDED
Binary file (20.8 kB). View file
|
|
ComfyUI/comfy/__pycache__/model_management.cpython-39.pyc
ADDED
Binary file (21 kB). View file
|
|
ComfyUI/comfy/__pycache__/model_patcher.cpython-310.pyc
ADDED
Binary file (15.9 kB). View file
|
|
ComfyUI/comfy/__pycache__/model_patcher.cpython-39.pyc
ADDED
Binary file (15.7 kB). View file
|
|
ComfyUI/comfy/__pycache__/model_sampling.cpython-310.pyc
ADDED
Binary file (10.9 kB). View file
|
|
ComfyUI/comfy/__pycache__/ops.cpython-310.pyc
ADDED
Binary file (9.68 kB). View file
|
|
ComfyUI/comfy/__pycache__/ops.cpython-39.pyc
ADDED
Binary file (9.24 kB). View file
|
|
ComfyUI/comfy/__pycache__/options.cpython-310.pyc
ADDED
Binary file (294 Bytes). View file
|
|
ComfyUI/comfy/__pycache__/options.cpython-39.pyc
ADDED
Binary file (294 Bytes). View file
|
|
ComfyUI/comfy/__pycache__/sa_t5.cpython-310.pyc
ADDED
Binary file (2.21 kB). View file
|
|
ComfyUI/comfy/__pycache__/sample.cpython-310.pyc
ADDED
Binary file (2.88 kB). View file
|
|
ComfyUI/comfy/__pycache__/sampler_helpers.cpython-310.pyc
ADDED
Binary file (2.64 kB). View file
|
|
ComfyUI/comfy/__pycache__/samplers.cpython-310.pyc
ADDED
Binary file (22.7 kB). View file
|
|
ComfyUI/comfy/__pycache__/sd.cpython-310.pyc
ADDED
Binary file (22.8 kB). View file
|
|
ComfyUI/comfy/__pycache__/sd.cpython-39.pyc
ADDED
Binary file (23.1 kB). View file
|
|
ComfyUI/comfy/__pycache__/sd1_clip.cpython-310.pyc
ADDED
Binary file (17.2 kB). View file
|
|
ComfyUI/comfy/__pycache__/sd2_clip.cpython-310.pyc
ADDED
Binary file (2 kB). View file
|
|
ComfyUI/comfy/__pycache__/sd3_clip.cpython-310.pyc
ADDED
Binary file (6.32 kB). View file
|
|
ComfyUI/comfy/__pycache__/sdxl_clip.cpython-310.pyc
ADDED
Binary file (5.65 kB). View file
|
|
ComfyUI/comfy/__pycache__/supported_models.cpython-310.pyc
ADDED
Binary file (18.1 kB). View file
|
|
ComfyUI/comfy/__pycache__/supported_models_base.cpython-310.pyc
ADDED
Binary file (4.01 kB). View file
|
|
ComfyUI/comfy/__pycache__/t5.cpython-310.pyc
ADDED
Binary file (9.83 kB). View file
|
|
ComfyUI/comfy/__pycache__/types.cpython-310.pyc
ADDED
Binary file (1.37 kB). View file
|
|