154 lines
4.3 KiB
Python
154 lines
4.3 KiB
Python
def test_model_dataclasses_are_importable():
|
|
from smart_metadata_reader.models import (
|
|
LoraInfo,
|
|
MetadataBundle,
|
|
NodeRecord,
|
|
ParseResult,
|
|
PromptSegment,
|
|
)
|
|
|
|
bundle = MetadataBundle(
|
|
filename="sample.png",
|
|
width=512,
|
|
height=768,
|
|
prompt_raw=None,
|
|
workflow_raw=None,
|
|
parameters_raw=None,
|
|
source_format="none",
|
|
)
|
|
node = NodeRecord(node_id="1", class_type="CLIPTextEncode", inputs={})
|
|
segment = PromptSegment(
|
|
text="character trigger",
|
|
node_id="1",
|
|
class_type="CLIPTextEncode",
|
|
field="text",
|
|
path=["CLIPTextEncode 1.text"],
|
|
)
|
|
lora = LoraInfo(
|
|
node_id="2",
|
|
class_type="LoraLoader",
|
|
lora_name="character.safetensors",
|
|
strength_model=0.8,
|
|
strength_clip=1.0,
|
|
path=["KSampler 3.model", "LoraLoader 2"],
|
|
)
|
|
result = ParseResult(
|
|
positive="character trigger",
|
|
negative="",
|
|
filename=bundle.filename,
|
|
loras=[lora],
|
|
)
|
|
|
|
assert node.node_id == "1"
|
|
assert segment.text == "character trigger"
|
|
assert result.seed == -1
|
|
assert result.steps == 0
|
|
assert result.cfg == 0.0
|
|
assert result.width == 0
|
|
assert result.height == 0
|
|
|
|
|
|
def test_graph_index_reads_api_prompt_nodes_as_primary_records():
|
|
from smart_metadata_reader.graph import GraphIndex
|
|
|
|
prompt = {
|
|
"6": {
|
|
"class_type": "CLIPTextEncode",
|
|
"inputs": {"text": ["22", 0]},
|
|
},
|
|
"22": {
|
|
"class_type": "StringFunction|pysssss",
|
|
"inputs": {"text_a": "character trigger"},
|
|
},
|
|
}
|
|
workflow = {
|
|
"nodes": [
|
|
{
|
|
"id": 6,
|
|
"type": "CLIPTextEncode",
|
|
"inputs": {"text": "stale widget text"},
|
|
}
|
|
]
|
|
}
|
|
|
|
graph = GraphIndex(prompt=prompt, workflow=workflow)
|
|
|
|
node = graph.get_node("6")
|
|
assert node.class_type == "CLIPTextEncode"
|
|
assert node.inputs["text"] == ["22", 0]
|
|
assert graph.get_node(22).class_type == "StringFunction|pysssss"
|
|
|
|
|
|
def test_graph_index_reads_ui_workflow_nodes_when_prompt_is_absent():
|
|
from smart_metadata_reader.graph import GraphIndex
|
|
|
|
workflow = {
|
|
"nodes": [
|
|
{
|
|
"id": 1,
|
|
"type": "PrimitiveString",
|
|
"inputs": {"text": "workflow text"},
|
|
"widgets_values": ["workflow widget"],
|
|
}
|
|
]
|
|
}
|
|
|
|
graph = GraphIndex(prompt=None, workflow=workflow)
|
|
|
|
node = graph.get_node("1")
|
|
assert node.class_type == "PrimitiveString"
|
|
assert node.inputs["text"] == "workflow text"
|
|
assert node.widgets_values == ["workflow widget"]
|
|
|
|
|
|
def test_graph_index_detects_links_and_downstream_nodes():
|
|
from smart_metadata_reader.graph import GraphIndex
|
|
|
|
prompt = {
|
|
"1": {"class_type": "PrimitiveString", "inputs": {"text": "hello"}},
|
|
"2": {"class_type": "CLIPTextEncode", "inputs": {"text": ["1", 0]}},
|
|
"3": {"class_type": "KSampler", "inputs": {"positive": [2, 0]}},
|
|
}
|
|
|
|
graph = GraphIndex(prompt=prompt, workflow=None)
|
|
|
|
assert graph.is_link(["1", 0])
|
|
assert graph.is_link([1, 0])
|
|
assert graph.link_target([1, 0]) == ("1", 0)
|
|
assert graph.upstream_link_inputs("3") == [("positive", [2, 0])]
|
|
assert [node.node_id for node in graph.downstream_nodes("1")] == ["2"]
|
|
|
|
|
|
def test_workflow_cache_prefers_named_inputs_then_widget_values():
|
|
from smart_metadata_reader.graph import GraphIndex
|
|
|
|
prompt = {
|
|
"10": {
|
|
"class_type": "ShowText|pysssss",
|
|
"inputs": {"text": ["9", 0]},
|
|
},
|
|
"11": {
|
|
"class_type": "ShowText|pysssss",
|
|
"inputs": {"text": ["9", 0]},
|
|
},
|
|
}
|
|
workflow = {
|
|
"nodes": [
|
|
{
|
|
"id": 10,
|
|
"type": "ShowText|pysssss",
|
|
"inputs": {"text_0": "cached shown text"},
|
|
},
|
|
{
|
|
"id": 11,
|
|
"type": "ShowText|pysssss",
|
|
"widgets_values": ["widget cached text"],
|
|
},
|
|
]
|
|
}
|
|
|
|
graph = GraphIndex(prompt=prompt, workflow=workflow)
|
|
|
|
assert graph.workflow_cache_for("10", ["text_0", "text"]) == "cached shown text"
|
|
assert graph.workflow_cache_for("11", ["text_0"]) == "widget cached text"
|