fix: number choices (CreateVideo bit_depth 8) are saved and sent as numbers; text already saved ("8") is read back as the number

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
digital-garbage
2026-10-07 15:59:49 +03:00
co-authored by Claude Opus 5.5
parent 8f63ee0b7a
commit 32eaf6881e
3 changed files with 18 additions and 1 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ export const widgetControl = (w, current, set) => {
// Nothing chosen shows as nothing chosen: showing the first file would look picked while the run has none
// (and with one file there is nothing to change to, so it could never be picked).
const options = [...(unset ? [{ value: "", label: "— choose —" }] : []), ...choices.map((v) => ({ value: v, label: String(v) }))];
return choices.length ? c.select.md({ label, value: unset ? "" : current, options, onChange: (v) => { if (v !== "") set(v); } })
return choices.length ? c.select.md({ label, value: unset ? "" : current, options, onChange: (v) => { if (v !== "") set(choices.find((x) => String(x) === String(v)) ?? v); } }) // the choice itself: a select gives back text, and ComfyUI refuses "8" for 8
: c.hint.default({ text: "No choices available — nothing found in the models folder." });
}
if (w.type === "INT" || w.type === "FLOAT") {
+10
View File
@@ -291,6 +291,7 @@ def build(slots: Sequence[dict], schemas: Optional[Schemas] = None) -> Tuple[dic
continue
inputs[name] = [source, index]
else:
value = as_choice(value, limits.get(name))
problem = unacceptable(name, value, limits.get(name))
if problem:
# An input the app writes under a name the person sees (Length, Width) is refused by that name.
@@ -311,6 +312,15 @@ def build(slots: Sequence[dict], schemas: Optional[Schemas] = None) -> Tuple[dic
return prompt, problems
def as_choice(value: Any, bounds: Optional[dict]) -> Any:
"""A combo choice saved as text ("8") back to the choice it names (8). A web page's select hands back
text whatever it was given, and ComfyUI refuses "8" from a list holding the number 8."""
choices = (bounds or {}).get("choices")
if isinstance(value, str) and choices and value not in choices:
return next((c for c in choices if not isinstance(c, str) and str(c) == value), value)
return value
def unacceptable(name: str, value: Any, bounds: Optional[dict]) -> Optional[str]:
"""Why this literal will not do, or None.
+7
View File
@@ -595,3 +595,10 @@ def test_a_swap_keeps_only_the_roles_the_new_node_can_still_take():
swapped, problems = graph.replace(slots, "empty", "Empty", SCHEMAS)
assert problems == []
assert graph.slots_by_id(swapped)["empty"]["roles"] == [{"at": "project.video", "input": "width"}]
def test_a_numeric_combo_choice_saved_as_text_is_sent_as_the_number():
bounds = {"choices": ["auto", 8, 10]}
assert graph.as_choice("8", bounds) == 8 and graph.unacceptable("bit_depth", 8, bounds) is None
assert graph.as_choice("auto", bounds) == "auto"
assert graph.as_choice("9", bounds) == "9", "not a choice: left as it is, and refused by name"