Repository navigation
Conversation
|
✅ All contributors have signed the CLA. Thank you! This PR is ready to be merged. |
|
I have read and agree to the Contributor License Agreement |
jaeone94
left a comment
There was a problem hiding this comment.
Thanks for the clear writeup. I reproduced the bug locally: the new TestRecordWidgetValues cases fail on main (8 failures) and pass on this branch, and the full CI matrix is green after I approved the runs. The fix itself is small and correct for record slots like ImageCropV2.crop_region, and Power Lora Loader still takes the self-naming path since its schema declares no widgets.
One behavior worth a decision, plus a few small cleanups inline.
Mixed nodes (declared widgets + self-named dicts). The new gate checks "does the schema declare any widget", not "does this dict sit in a declared slot". So a custom node that declares scalar widgets and also saves frontend-only dicts now takes the positional walk:
widgets_values (schema declares seed, text) |
main | this PR |
|---|---|---|
[5, "hi", {"type": "Hdr"}] |
seed/text fall back to defaults, Hdr kept |
seed=5, text="hi", Hdr dropped |
[{"type": "Hdr"}, 5, "hi"] |
seed/text fall back to defaults, Hdr kept |
seed={"type": "Hdr"}, text=5 (shifted; fails server validation) |
Main was already wrong for these nodes, and I couldn't find a real node with this layout, so I don't think this blocks. If you want to cover it, one option is to run the schema walk first and only hand the values left over after the declared slots to _absorb_dict_widget_values. Either way, a test pinning whichever behavior you pick for the mixed case would be nice.
|
|
||
| if any(isinstance(v, dict) for v in widget_values): | ||
| schema_widgets = any(_is_widget_input(spec)[0] for spec in input_specs) if schema else False | ||
| # Declared widget slots can hold records; keep the self-naming layout for nodes without those slots. |
There was a problem hiding this comment.
nit: the comment reads as if the gate looks for slots that accept records, but it triggers on any declared widget. Maybe something like:
| # Declared widget slots can hold records; keep the self-naming layout for nodes without those slots. | |
| # Any schema-declared widget means widgets_values is positional; only schema-less layouts self-name via dicts. |
| @@ -1683,7 +1685,6 @@ def emit(name: str, value: Any) -> Any: | |||
| # (e.g. ``COMFY_AUTOGROW_V3`` images) so they never consume a value slot. | |||
| schema = _schema_for(node_type, node, object_info) | |||
There was a problem hiding this comment.
nit: schema is already resolved at the top of the function with the same arguments, and schema_widgets now relies on that earlier value. This second lookup can go so nobody wonders whether the two could differ.
| - Preserve record-valued widgets such as `ImageCropV2.crop_region` during | ||
| UI-to-API workflow conversion instead of replacing them with schema defaults. | ||
|
|
There was a problem hiding this comment.
nit: the other entries in this section have no blank line between bullets and describe the user-visible outcome. Something like:
| - Preserve record-valued widgets such as `ImageCropV2.crop_region` during | |
| UI-to-API workflow conversion instead of replacing them with schema defaults. | |
| - Converting a UI workflow to API format keeps a record widget's saved value, | |
| such as `ImageCropV2.crop_region`, instead of replacing it with the schema | |
| default. |
jaeone94
left a comment
There was a problem hiding this comment.
Thanks for the quick follow-up, LGTM.
UI-to-API conversion routes any dictionary in
widgets_valuesthrough the self-naming custom-widget layout. ForImageCropV2, that drops a saved 1669×2688crop_regionand replaces it with the 512×512 schema default.Use the existing schema widget classification before that fallback so declared record-valued slots follow the positional schema walk. Preserve the legacy layout for nodes without declared widget slots, with regressions for UI trailers, opaque records, linked inputs, and PowerLoRA controls.
Validation:
ruff check .andruff format --check .pass (ruff 0.15.15).pytest . -q: 10,112 passed, 39 skipped on Linux arm64 / uv-managed Python 3.10.20, using locked project dependencies and prepared pip/fixture caches for offline execution.An earlier macOS/Python 3.12 full run was not clean: global telemetry opt-out settings interfered with tracking tests (204 pass when corrected), a CA assertion also fails on the unchanged base, and a pretty-output assertion did not reproduce in isolation.
AI-assisted implementation, testing, and review.
Fixes #1011.