dikdimon's picture
Upload stable-diffusion-webui-prompt-parser8 using SD-Hub
6d53c19 verified
raw
history blame
5.09 kB
from dataclasses import dataclass, field
from typing import Literal, List, Dict, Any, Callable, Optional
BlockType = Literal["plain","sequence","grouped","scheduled","alternate","alternate_distinct","numbered","and_rule","top_level"]
@dataclass
class FieldSpec:
name: str
kind: Literal["text","number","choice","list","boolean"] = "text"
required: bool = True
choices: Optional[List[str]] = None
default: Any = None
help: str = ""
@dataclass
class Constraint:
check: Callable[[Dict[str, Any]], bool]
message: str
@dataclass
class FormatBlueprint:
id: str
title: str
block_type: BlockType
fields: List[FieldSpec] = field(default_factory=list)
assemble: Callable[[Dict[str, Any]], str] = lambda v: v.get("text","")
constraints: List[Constraint] = field(default_factory=list)
def _pairs_from_list(v) -> List[Dict[str, str]]:
out = []
for x in v or []:
if isinstance(x, dict) and "key" in x and "val" in x:
out.append({"key": str(x["key"]), "val": str(x["val"])})
return out
def bp_top_level():
def assemble(v):
owner = (v.get("owner") or "").strip()
pairs = _pairs_from_list(v.get("pairs"))
body = " ".join([f":: {p['key'].strip()} :: {p['val'].strip()} ;" for p in pairs])
return f"{owner} {body} !!".strip()
return FormatBlueprint(
id="top_level_simple",
title="Top-level (owner :: key :: val ; ... !!)",
block_type="top_level",
fields=[
FieldSpec("owner", help="Например: portrait"),
FieldSpec("pairs", kind="list", help="Список пар key/val"),
],
assemble=assemble,
constraints=[
Constraint(lambda v: bool((v.get("owner") or "").strip()), "owner пуст"),
],
)
def bp_sequence():
def assemble(v):
items = [str(x).strip() for x in (v.get("items") or []) if str(x).strip()]
if not items:
return ""
inner = " , ".join(items)
return f"{{ {inner} }} ;"
return FormatBlueprint(
id="sequence_simple",
title="Sequence { a , b , c } ;",
block_type="sequence",
fields=[FieldSpec("items", kind="list", help="Список элементов")],
assemble=assemble,
constraints=[Constraint(lambda v: len(v.get("items") or [])>=1, "Нужно >=1 элемента")],
)
def bp_numbered():
def assemble(v):
n = int(v.get("count") or 1)
marker = str(v.get("marker") or "").strip() # "", "!", "_"
options = [str(x).strip() for x in (v.get("options") or []) if str(x).strip()]
inside = " | ".join(options)
return f"{n}{marker} {{ {inside} }}"
return FormatBlueprint(
id="numbered_simple",
title="Numbered (N[!|_] { a | b | c })",
block_type="numbered",
fields=[
FieldSpec("count", kind="number", default=3, help="Сколько выбрать"),
FieldSpec("marker", kind="choice", choices=["", "!", "_"], default="!"),
FieldSpec("options", kind="list", help="Опции в { }"),
],
assemble=assemble,
constraints=[
Constraint(lambda v: int(v.get("count") or 0)>=1, "count >= 1"),
Constraint(lambda v: len(v.get("options") or [])>=1, "Требуется >=1 опции"),
],
)
def bp_alternate():
def assemble(v):
opts = [str(x).strip() for x in (v.get("options") or []) if str(x).strip()]
body = " | ".join(opts)
distinct = bool(v.get("distinct") or False)
return f"[ {body} ]!" if distinct else f"[ {body} ]"
return FormatBlueprint(
id="alternate_simple",
title="Alternate [ a | b | c ] (! для distinct)",
block_type="alternate",
fields=[
FieldSpec("options", kind="list", help="Опции в []"),
FieldSpec("distinct", kind="boolean", default=False, help="Добавить !"),
],
assemble=assemble,
constraints=[Constraint(lambda v: len(v.get("options") or [])>=1, "Требуется >=1 опции")],
)
def bp_scheduled():
# [ a : b : c ] : 10-50%
def assemble(v):
parts = [str(x).strip() for x in (v.get("parts") or []) if str(x).strip()]
tail = (v.get("tail") or "").strip()
return f"[ {' : '.join(parts)} ] : {tail}"
return FormatBlueprint(
id="scheduled_simple",
title="Scheduled [ a : b : ... ] : 10-50%",
block_type="scheduled",
fields=[
FieldSpec("parts", kind="list", help="Секции внутри [] через ':'"),
FieldSpec("tail", kind="text", default="50", help="Число/диапазон/проценты"),
],
assemble=assemble,
constraints=[Constraint(lambda v: len(v.get('parts') or [])>=1, "Нужна >=1 секция")],
)
def get_blueprints():
return [
bp_top_level(),
bp_sequence(),
bp_numbered(),
bp_alternate(),
bp_scheduled(),
]