Fix 25+ bugs across rounds 4-8 of comprehensive code review

history_tree.py:
- Cycle protection in generate_graph() parent walk
- KeyError → .get() for malformed node data in commit() and generate_graph()
- UUID collision check with for/else raise in commit() and _migrate_legacy()
- RuntimeError → ValueError for consistent exception handling

tab_timeline_ng.py:
- Re-parent children walks to surviving ancestor for batch deletes
- Branch tip deletion re-points to parent instead of removing branch
- Cycle protection in _walk_branch_nodes and _find_branch_for_node
- Full data.clear() restore instead of merge in _restore_node
- Safe .get('data', {}) in restore and preview
- Reset stale branch selection after node deletion
- json.dumps for safe JS string escaping in graphviz renderer

tab_batch_ng.py:
- NaN/inf rejection in dict_number with math.isfinite()
- _safe_int used in recalc_vace, update_mode_label, frame_to_skip
- Uncaught ValueError from htree.commit() caught with user notification

tab_comfy_ng.py:
- asyncio.get_event_loop() → get_running_loop()

utils.py:
- Atomic writes for save_config and save_snippets
- save_config extra_data can't override explicit last_dir/favorites

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-02 10:23:14 +01:00
parent 04b9ed0e27
commit b042fe4368
5 changed files with 117 additions and 37 deletions

View File

@@ -139,7 +139,7 @@ def _render_single_instance(state: AppState, instance_config: dict, index: int,
async def refresh_status():
status_container.clear()
loop = asyncio.get_event_loop()
loop = asyncio.get_running_loop()
res, err = await loop.run_in_executor(
None, lambda: _fetch_blocking(f'{comfy_url}/queue'))
with status_container:
@@ -237,7 +237,7 @@ def _render_single_instance(state: AppState, instance_config: dict, index: int,
async def check_image():
img_container.clear()
loop = asyncio.get_event_loop()
loop = asyncio.get_running_loop()
res, err = await loop.run_in_executor(
None, lambda: _fetch_blocking(f'{comfy_url}/history', timeout=2))
with img_container: