Fix 7 bugs: async proxies, mode default, JS key serialization, validation
- Use asyncio.to_thread for proxy endpoints to avoid blocking event loop - Add mode to DEFAULTS so it doesn't silently insert 0 - Use JSON serialization for keys in project_dynamic.js (with comma fallback) - Validate path exists in change_path, friendly error on duplicate rename - Remove unused exp param from rename closure - Use deepcopy for DEFAULTS consistently Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import urllib.parse
|
||||
@@ -88,7 +89,7 @@ if PromptServer is not None:
|
||||
async def list_projects_proxy(request):
|
||||
manager_url = request.query.get("url", "http://localhost:8080")
|
||||
url = f"{manager_url.rstrip('/')}/api/projects"
|
||||
data = _fetch_json(url)
|
||||
data = await asyncio.to_thread(_fetch_json, url)
|
||||
return web.json_response(data)
|
||||
|
||||
@PromptServer.instance.routes.get("/json_manager/list_project_files")
|
||||
@@ -96,7 +97,7 @@ if PromptServer is not None:
|
||||
manager_url = request.query.get("url", "http://localhost:8080")
|
||||
project = urllib.parse.quote(request.query.get("project", ""), safe='')
|
||||
url = f"{manager_url.rstrip('/')}/api/projects/{project}/files"
|
||||
data = _fetch_json(url)
|
||||
data = await asyncio.to_thread(_fetch_json, url)
|
||||
return web.json_response(data)
|
||||
|
||||
@PromptServer.instance.routes.get("/json_manager/list_project_sequences")
|
||||
@@ -105,7 +106,7 @@ if PromptServer is not None:
|
||||
project = urllib.parse.quote(request.query.get("project", ""), safe='')
|
||||
file_name = urllib.parse.quote(request.query.get("file", ""), safe='')
|
||||
url = f"{manager_url.rstrip('/')}/api/projects/{project}/files/{file_name}/sequences"
|
||||
data = _fetch_json(url)
|
||||
data = await asyncio.to_thread(_fetch_json, url)
|
||||
return web.json_response(data)
|
||||
|
||||
@PromptServer.instance.routes.get("/json_manager/get_project_keys")
|
||||
@@ -117,7 +118,7 @@ if PromptServer is not None:
|
||||
seq = int(request.query.get("seq", "1"))
|
||||
except (ValueError, TypeError):
|
||||
seq = 1
|
||||
data = _fetch_keys(manager_url, project, file_name, seq)
|
||||
data = await asyncio.to_thread(_fetch_keys, manager_url, project, file_name, seq)
|
||||
if data.get("error") in ("http_error", "network_error", "parse_error"):
|
||||
status = data.get("status", 502)
|
||||
return web.json_response(data, status=status)
|
||||
|
||||
@@ -267,7 +267,7 @@ def render_batch_processor(state: AppState):
|
||||
|
||||
with ui.row().classes('q-mt-sm'):
|
||||
def add_empty():
|
||||
_add_sequence(DEFAULTS.copy())
|
||||
_add_sequence(copy.deepcopy(DEFAULTS))
|
||||
|
||||
def add_from_source():
|
||||
item = copy.deepcopy(DEFAULTS)
|
||||
@@ -383,7 +383,7 @@ def _render_sequence_card(i, seq, batch_list, data, file_path, state,
|
||||
# --- Action row ---
|
||||
with ui.row().classes('w-full q-gutter-sm action-row'):
|
||||
# Rename
|
||||
async def rename(idx=i, s=seq, exp=expansion):
|
||||
async def rename(s=seq):
|
||||
result = await ui.run_javascript(
|
||||
f'prompt("Rename sequence:", {json.dumps(s.get("name", ""))})',
|
||||
timeout=30.0,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import json
|
||||
import logging
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
|
||||
from nicegui import ui
|
||||
@@ -127,6 +128,9 @@ def render_projects_tab(state: AppState):
|
||||
state.config)
|
||||
ui.notify(f'Renamed to "{new_name}"', type='positive')
|
||||
render_project_list.refresh()
|
||||
except sqlite3.IntegrityError:
|
||||
ui.notify(f'A project named "{new_name}" already exists',
|
||||
type='warning')
|
||||
except Exception as e:
|
||||
ui.notify(f'Error: {e}', type='negative')
|
||||
|
||||
@@ -140,6 +144,9 @@ def render_projects_tab(state: AppState):
|
||||
)
|
||||
if new_path and new_path.strip() and new_path.strip() != path:
|
||||
new_path = new_path.strip()
|
||||
if not Path(new_path).is_dir():
|
||||
ui.notify(f'Warning: "{new_path}" does not exist',
|
||||
type='warning')
|
||||
state.db.update_project_path(name, new_path)
|
||||
ui.notify(f'Path updated to "{new_path}"', type='positive')
|
||||
render_project_list.refresh()
|
||||
|
||||
1
utils.py
1
utils.py
@@ -30,6 +30,7 @@ DEFAULTS = {
|
||||
"cfg": 1.5,
|
||||
|
||||
# --- Settings ---
|
||||
"mode": 0,
|
||||
"camera": "static",
|
||||
"flf": 0.0,
|
||||
|
||||
|
||||
@@ -117,11 +117,11 @@ app.registerExtension({
|
||||
return;
|
||||
}
|
||||
|
||||
// Store keys and types in hidden widgets for persistence (comma-separated)
|
||||
// Store keys and types in hidden widgets for persistence (JSON)
|
||||
const okWidget = this.widgets?.find(w => w.name === "output_keys");
|
||||
if (okWidget) okWidget.value = keys.join(",");
|
||||
if (okWidget) okWidget.value = JSON.stringify(keys);
|
||||
const otWidget = this.widgets?.find(w => w.name === "output_types");
|
||||
if (otWidget) otWidget.value = types.join(",");
|
||||
if (otWidget) otWidget.value = JSON.stringify(types);
|
||||
|
||||
// Slot 0 is always total_sequences (INT) — ensure it exists
|
||||
if (this.outputs.length === 0 || this.outputs[0].name !== "total_sequences") {
|
||||
@@ -198,12 +198,18 @@ app.registerExtension({
|
||||
const okWidget = this.widgets?.find(w => w.name === "output_keys");
|
||||
const otWidget = this.widgets?.find(w => w.name === "output_types");
|
||||
|
||||
const keys = okWidget?.value
|
||||
? okWidget.value.split(",").filter(k => k.trim())
|
||||
: [];
|
||||
const types = otWidget?.value
|
||||
? otWidget.value.split(",")
|
||||
: [];
|
||||
let keys = [];
|
||||
let types = [];
|
||||
if (okWidget?.value) {
|
||||
try { keys = JSON.parse(okWidget.value); } catch (_) {
|
||||
keys = okWidget.value.split(",").filter(k => k.trim());
|
||||
}
|
||||
}
|
||||
if (otWidget?.value) {
|
||||
try { types = JSON.parse(otWidget.value); } catch (_) {
|
||||
types = otWidget.value.split(",");
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure slot 0 is total_sequences (INT)
|
||||
if (this.outputs.length === 0 || this.outputs[0].name !== "total_sequences") {
|
||||
|
||||
Reference in New Issue
Block a user