mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-05-28 18:07:25 +08:00
Compare commits
8 Commits
16030fc3a4
...
45ac2e95d0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45ac2e95d0 | ||
|
|
e35348aa53 | ||
|
|
cd8c7a2306 | ||
|
|
6bcd8b96ab | ||
|
|
1ff7347993 | ||
|
|
e1f652a81c | ||
|
|
9c3897b3c0 | ||
|
|
43f2440972 |
2
.github/workflows/stable-release.yml
vendored
2
.github/workflows/stable-release.yml
vendored
@ -145,6 +145,8 @@ jobs:
|
||||
cp -r ComfyUI/.ci/windows_${{ inputs.rel_name }}_base_files/* ./
|
||||
cp ../update_comfyui_and_python_dependencies.bat ./update/
|
||||
|
||||
echo 'local-portable' > ComfyUI/.comfy_environment
|
||||
|
||||
cd ..
|
||||
|
||||
"C:\Program Files\7-Zip\7z.exe" a -t7z -m0=lzma2 -mx=9 -mfb=128 -md=768m -ms=on -mf=BCJ2 ComfyUI_windows_portable.7z ComfyUI_windows_portable
|
||||
|
||||
@ -26,6 +26,7 @@ import uuid
|
||||
from typing import Callable, Optional
|
||||
|
||||
import torch
|
||||
import tqdm
|
||||
|
||||
import comfy.float
|
||||
import comfy.hooks
|
||||
@ -1651,7 +1652,11 @@ class ModelPatcherDynamic(ModelPatcher):
|
||||
self.model.model_loaded_weight_memory += casted_buf.numel() * casted_buf.element_size()
|
||||
|
||||
force_load_stat = f" Force pre-loaded {len(self.backup)} weights: {self.model.model_loaded_weight_memory // 1024} KB." if len(self.backup) > 0 else ""
|
||||
logging.info(f"Model {self.model.__class__.__name__} prepared for dynamic VRAM loading. {allocated_size // (1024 ** 2)}MB Staged. {num_patches} patches attached.{force_load_stat}")
|
||||
log_key = (self.patches_uuid, allocated_size, num_patches, len(self.backup), self.model.model_loaded_weight_memory)
|
||||
in_loop = bool(getattr(tqdm.tqdm, "_instances", None))
|
||||
level = logging.DEBUG if in_loop and getattr(self, "_last_prepare_log_key", None) == log_key else logging.INFO
|
||||
self._last_prepare_log_key = log_key
|
||||
logging.log(level, f"Model {self.model.__class__.__name__} prepared for dynamic VRAM loading. {allocated_size // (1024 ** 2)}MB Staged. {num_patches} patches attached.{force_load_stat}")
|
||||
|
||||
self.model.device = device_to
|
||||
self.model.current_weight_patches_uuid = self.patches_uuid
|
||||
|
||||
@ -63,7 +63,7 @@ class MathExpressionNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
autogrow = io.Autogrow.TemplateNames(
|
||||
input=io.MultiType.Input("value", [io.Float, io.Int]),
|
||||
input=io.MultiType.Input("value", [io.Float, io.Int, io.Boolean]),
|
||||
names=list(string.ascii_lowercase),
|
||||
min=1,
|
||||
)
|
||||
@ -82,6 +82,7 @@ class MathExpressionNode(io.ComfyNode):
|
||||
outputs=[
|
||||
io.Float.Output(display_name="FLOAT"),
|
||||
io.Int.Output(display_name="INT"),
|
||||
io.Boolean.Output(display_name="BOOL"),
|
||||
],
|
||||
)
|
||||
|
||||
@ -97,7 +98,7 @@ class MathExpressionNode(io.ComfyNode):
|
||||
|
||||
result = simple_eval(expression, names=context, functions=MATH_FUNCTIONS)
|
||||
# bool check must come first because bool is a subclass of int in Python
|
||||
if isinstance(result, bool) or not isinstance(result, (int, float)):
|
||||
if not isinstance(result, (int, float)):
|
||||
raise ValueError(
|
||||
f"Math Expression '{expression}' must evaluate to a numeric result, "
|
||||
f"got {type(result).__name__}: {result!r}"
|
||||
@ -106,7 +107,7 @@ class MathExpressionNode(io.ComfyNode):
|
||||
raise ValueError(
|
||||
f"Math Expression '{expression}' produced a non-finite result: {result}"
|
||||
)
|
||||
return io.NodeOutput(float(result), int(result))
|
||||
return io.NodeOutput(float(result), int(result), bool(result))
|
||||
|
||||
|
||||
class MathExtension(ComfyExtension):
|
||||
|
||||
@ -560,7 +560,7 @@ class PromptServer():
|
||||
buffer.seek(0)
|
||||
|
||||
return web.Response(body=buffer.read(), content_type=f'image/{image_format}',
|
||||
headers={"Content-Disposition": f"attachment; filename=\"{filename}\""})
|
||||
headers={"Content-Disposition": f"filename=\"{filename}\""})
|
||||
|
||||
if 'channel' not in request.rel_url.query:
|
||||
channel = 'rgba'
|
||||
@ -580,7 +580,7 @@ class PromptServer():
|
||||
buffer.seek(0)
|
||||
|
||||
return web.Response(body=buffer.read(), content_type='image/png',
|
||||
headers={"Content-Disposition": f"attachment; filename=\"{filename}\""})
|
||||
headers={"Content-Disposition": f"filename=\"{filename}\""})
|
||||
|
||||
elif channel == 'a':
|
||||
with Image.open(file) as img:
|
||||
@ -597,7 +597,7 @@ class PromptServer():
|
||||
alpha_buffer.seek(0)
|
||||
|
||||
return web.Response(body=alpha_buffer.read(), content_type='image/png',
|
||||
headers={"Content-Disposition": f"attachment; filename=\"{filename}\""})
|
||||
headers={"Content-Disposition": f"filename=\"{filename}\""})
|
||||
else:
|
||||
# Use the content type from asset resolution if available,
|
||||
# otherwise guess from the filename.
|
||||
@ -614,7 +614,7 @@ class PromptServer():
|
||||
return web.FileResponse(
|
||||
file,
|
||||
headers={
|
||||
"Content-Disposition": f"attachment; filename=\"{filename}\"",
|
||||
"Content-Disposition": f"filename=\"{filename}\"",
|
||||
"Content-Type": content_type
|
||||
}
|
||||
)
|
||||
|
||||
@ -124,9 +124,11 @@ class TestMathExpressionExecute:
|
||||
with pytest.raises(Exception, match="not defined"):
|
||||
self._exec("str(a)", a=42)
|
||||
|
||||
def test_boolean_result_raises(self):
|
||||
with pytest.raises(ValueError, match="got bool"):
|
||||
self._exec("a > b", a=5, b=3)
|
||||
def test_boolean_result(self):
|
||||
result = self._exec("a > b", a=5, b=3)
|
||||
assert result[2] is True
|
||||
result = self._exec("a > b", a=3, b=5)
|
||||
assert result[2] is False
|
||||
|
||||
def test_empty_expression_raises(self):
|
||||
with pytest.raises(ValueError, match="Expression cannot be empty"):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user