131 lines
4.0 KiB
Python
131 lines
4.0 KiB
Python
import importlib.util
|
|
import json
|
|
import pathlib
|
|
import sys
|
|
import unittest
|
|
|
|
|
|
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def load_plugin_package():
|
|
spec = importlib.util.spec_from_file_location(
|
|
"lls_node_test_compat",
|
|
ROOT / "__init__.py",
|
|
submodule_search_locations=[str(ROOT)],
|
|
)
|
|
module = importlib.util.module_from_spec(spec)
|
|
sys.modules["lls_node_test_compat"] = module
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
class LegacyClipStub:
|
|
def __init__(self):
|
|
self.layer = None
|
|
|
|
def clone(self):
|
|
cloned = LegacyClipStub()
|
|
cloned.layer = self.layer
|
|
return cloned
|
|
|
|
def clip_layer(self, layer):
|
|
self.layer = layer
|
|
|
|
def tokenize(self, text):
|
|
return {"text": text}
|
|
|
|
def encode_from_tokens(self, tokens, return_pooled=False):
|
|
if not return_pooled:
|
|
raise AssertionError("legacy path should request pooled output")
|
|
cond = f"cond::{tokens['text']}"
|
|
pooled = f"pooled::{tokens['text']}"
|
|
return cond, pooled
|
|
|
|
|
|
class UniversalClipStub:
|
|
def tokenize(self, text):
|
|
return {"text": text}
|
|
|
|
def encode_from_tokens(self, tokens, return_pooled=False):
|
|
if not return_pooled:
|
|
raise AssertionError("legacy path should request pooled output")
|
|
return f"cond::{tokens['text']}", f"pooled::{tokens['text']}"
|
|
|
|
|
|
class TestConditioningCompatibility(unittest.TestCase):
|
|
def test_simple_prompt_encode_schema_accepts_legacy_none_clip_skip(self):
|
|
plugin = load_plugin_package()
|
|
node_cls = plugin.NODE_CLASS_MAPPINGS["LLSSimplePromptEncode"]
|
|
clip_skip_type, clip_skip_config = node_cls.INPUT_TYPES()["required"]["clip_skip"]
|
|
|
|
self.assertIsInstance(clip_skip_type, list)
|
|
self.assertIn(None, clip_skip_type)
|
|
self.assertEqual(clip_skip_config["default"], -1)
|
|
|
|
def test_simple_prompt_encode_falls_back_for_legacy_clip(self):
|
|
plugin = load_plugin_package()
|
|
node_cls = plugin.NODE_CLASS_MAPPINGS["LLSSimplePromptEncode"]
|
|
node = node_cls()
|
|
|
|
positive, negative, prompt_info = node.encode(
|
|
clip=LegacyClipStub(),
|
|
positive_prompt="a cat",
|
|
negative_prompt="low quality",
|
|
clip_skip=-2,
|
|
model_family="Auto",
|
|
)
|
|
|
|
self.assertEqual(
|
|
positive,
|
|
[["cond::a cat", {"pooled_output": "pooled::a cat"}]],
|
|
)
|
|
self.assertEqual(
|
|
negative,
|
|
[["cond::low quality", {"pooled_output": "pooled::low quality"}]],
|
|
)
|
|
payload = json.loads(prompt_info)
|
|
self.assertEqual(payload["clip_skip"], -2)
|
|
self.assertEqual(payload["prompt_mode"], "clip")
|
|
self.assertEqual(payload["model_family"], "SD1.5")
|
|
|
|
def test_simple_prompt_encode_normalizes_none_clip_skip(self):
|
|
plugin = load_plugin_package()
|
|
node_cls = plugin.NODE_CLASS_MAPPINGS["LLSSimplePromptEncode"]
|
|
node = node_cls()
|
|
|
|
positive, negative, prompt_info = node.encode(
|
|
clip=LegacyClipStub(),
|
|
positive_prompt="a cat",
|
|
negative_prompt="low quality",
|
|
clip_skip=None,
|
|
model_family="Auto",
|
|
)
|
|
|
|
self.assertEqual(
|
|
positive,
|
|
[["cond::a cat", {"pooled_output": "pooled::a cat"}]],
|
|
)
|
|
self.assertEqual(
|
|
negative,
|
|
[["cond::low quality", {"pooled_output": "pooled::low quality"}]],
|
|
)
|
|
payload = json.loads(prompt_info)
|
|
self.assertEqual(payload["clip_skip"], -1)
|
|
|
|
def test_universal_backend_falls_back_for_legacy_clip(self):
|
|
load_plugin_package()
|
|
from lls_node_test_compat.lls_universal.backend_sd15 import SD15Backend
|
|
|
|
backend = SD15Backend()
|
|
positive = backend._encode_standard_prompt(UniversalClipStub(), "hello")
|
|
|
|
self.assertEqual(
|
|
positive,
|
|
[["cond::hello", {"pooled_output": "pooled::hello"}]],
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|