Critical:
- rename nodes/ -> mp_nodes/, shared/ -> mp_shared/ to avoid shadowing
ComfyUI core's nodes.py via sys.path injection (root cause of v0.1.1
'nodes is not a package' startup failure)
- http_post now streams response and enforces 50MB cap mid-stream (DoS)
- AES key derivation: HKDF -> PBKDF2-HMAC-SHA256 600k iters + random salt
(work factor against weak-key brute force; ciphertext format changed)
- fs_mkdir/copy/move/delete confined to ComfyUI input/output/temp + ~ by
default; UTILITY_MEGAPACK_ALLOW_ARBITRARY_PATHS=1 to override
UX / correctness:
- combo settings now declare options array (themes dropdown was empty)
- LATENT default 1x4x8x8 zeros -> {} (avoids Flux/SD3 shape crashes)
- @op decorator rejects reserved widget names mode/theme at register time
- _pad_outputs docstring updated to match relaxed opaque-type behavior
74 lines
2.0 KiB
Python
74 lines
2.0 KiB
Python
"""Tests for MegaPackNodeBase.process — the per-execution dispatcher."""
|
|
|
|
import pytest
|
|
|
|
from mp_nodes._base import MegaPackNodeBase, OpRegistry
|
|
|
|
|
|
def _make_one_op_node():
|
|
reg = OpRegistry()
|
|
|
|
@reg.register(
|
|
op_id="echo",
|
|
display_name="Echo",
|
|
category="Test",
|
|
input_schema={"required": {"text": ("STRING", {"default": ""})}},
|
|
output_indices=(0,),
|
|
)
|
|
def echo(self, text):
|
|
return (text,)
|
|
|
|
class _N(MegaPackNodeBase):
|
|
REGISTRY = reg
|
|
RETURN_TYPES = ("STRING", "INT")
|
|
RETURN_NAMES = ("string", "int")
|
|
|
|
return _N
|
|
|
|
|
|
def test_process_dispatches_to_registered_op():
|
|
NodeCls = _make_one_op_node()
|
|
result = NodeCls().process(mode="echo", theme="(use pack default)", text="hello")
|
|
assert result[0] == "hello"
|
|
|
|
|
|
def test_process_pads_unfilled_outputs():
|
|
NodeCls = _make_one_op_node()
|
|
result = NodeCls().process(mode="echo", theme="(use pack default)", text="hi")
|
|
assert result == ("hi", 0)
|
|
|
|
|
|
def test_process_ignores_theme_argument():
|
|
"""The theme widget is UI-only; Python side just accepts and ignores it."""
|
|
NodeCls = _make_one_op_node()
|
|
result = NodeCls().process(mode="echo", theme="cyberpunk", text="x")
|
|
assert result[0] == "x"
|
|
|
|
|
|
def test_process_unknown_mode_raises_runtime_error():
|
|
NodeCls = _make_one_op_node()
|
|
with pytest.raises(RuntimeError, match="unknown mode"):
|
|
NodeCls().process(mode="not_a_real_mode", theme="(use pack default)", text="x")
|
|
|
|
|
|
def test_process_wraps_op_exceptions_with_context():
|
|
reg = OpRegistry()
|
|
|
|
@reg.register(
|
|
op_id="boom",
|
|
display_name="Boom",
|
|
category="Test",
|
|
input_schema={},
|
|
output_indices=(),
|
|
)
|
|
def boom(self):
|
|
raise ValueError("inner kaboom")
|
|
|
|
class _N(MegaPackNodeBase):
|
|
REGISTRY = reg
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("string",)
|
|
|
|
with pytest.raises(RuntimeError, match=r"\[_N/boom\] inner kaboom"):
|
|
_N().process(mode="boom", theme="(use pack default)")
|