Private
Public Access
0
0

fix(gui_2): initialize ui_synthesis_prompt/selected_takes to prevent crash

sloppy.py crashed on startup at gui_2.py:4006 with
TypeError: input_text_multiline(): incompatible function arguments.
The second positional arg (app.ui_synthesis_prompt) was None
when it should be str.

Root cause: the defensive guards
  if not hasattr(app, 'ui_synthesis_prompt'):
      app.ui_synthesis_prompt = ""
only fire if the attribute is MISSING — if it's set to None
elsewhere (e.g. via setattr from a config flush, or a plugin
side-effect), hasattr returns True and the value stays None.

Fix in 3 places:
1. App.__init__: initialize ui_synthesis_prompt = "" and
   ui_synthesis_selected_takes = {} at construction time
   alongside related context state (line 456).
2. render_synthesis_panel (line ~4002): harden the guard to
   check isinstance(getattr(...), str) — fixes the same
   pattern at its first call site.
3. render_takes_panel (line ~4139): same hardening at the
   second call site.

Verified by constructing App() in a fresh subprocess and
inspecting the attributes (ui_synthesis_prompt == "" and
ui_synthesis_selected_takes == {} both before and after
init_state()).

Manual smoke test: previously the app crashed before any
window was visible; now it renders the first frame.
This commit is contained in:
2026-06-07 17:07:40 -04:00
parent 864957e8e9
commit 8130ae34d4
+6 -4
View File
@@ -454,6 +454,8 @@ class App:
self._slice_sel_start = -1
self._slice_sel_end = -1
self.context_files = []
self.ui_synthesis_prompt: str = ""
self.ui_synthesis_selected_takes: dict[str, bool] = {}
# --- Rendering & Theme State ---
self.perf_show_graphs: dict[str, bool] = {}
self.ui_crt_filter = False
@@ -3998,8 +4000,8 @@ def render_synthesis_panel(app: App) -> None:
"""
imgui.text("Select takes to synthesize:")
discussions = app.project.get('discussion', {}).get('discussions', {})
if not hasattr(app, 'ui_synthesis_selected_takes'): app.ui_synthesis_selected_takes = {name: False for name in discussions}
if not hasattr(app, 'ui_synthesis_prompt'): app.ui_synthesis_prompt = ""
if not isinstance(getattr(app, 'ui_synthesis_selected_takes', None), dict): app.ui_synthesis_selected_takes = {name: False for name in discussions}
if not isinstance(getattr(app, 'ui_synthesis_prompt', None), str): app.ui_synthesis_prompt = ""
for name in discussions: _, app.ui_synthesis_selected_takes[name] = imgui.checkbox(name, app.ui_synthesis_selected_takes.get(name, False))
imgui.spacing()
imgui.text("Synthesis Prompt:")
@@ -4134,9 +4136,9 @@ def render_takes_panel(app: App) -> None:
imgui.text("Takes & Synthesis")
imgui.separator()
discussions = app.project.get('discussion', {}).get('discussions', {})
if not hasattr(app, 'ui_synthesis_selected_takes'):
if not isinstance(getattr(app, 'ui_synthesis_selected_takes', None), dict):
app.ui_synthesis_selected_takes = {name: False for name in discussions}
if not hasattr(app, 'ui_synthesis_prompt'):
if not isinstance(getattr(app, 'ui_synthesis_prompt', None), str):
app.ui_synthesis_prompt = ""
if imgui.begin_table("takes_table", 3, imgui.TableFlags_.resizable | imgui.TableFlags_.borders):
imgui.table_setup_column("Name", imgui.TableColumnFlags_.width_stretch)