diff --git a/src/app_controller.py b/src/app_controller.py index 312d1ade..4c8919a1 100644 --- a/src/app_controller.py +++ b/src/app_controller.py @@ -4011,7 +4011,7 @@ class AppController: return result self.submit_io(worker) - def _do_generate(self) -> tuple[str, Path, list[Metadata], str, str]: + def _do_generate(self) -> tuple[str, Path, list[FileItem], str, str]: """ Returns (full_md, output_path, file_items, stable_md, discussion_text). [C: src/gui_2.py:App._show_menus, tests/test_context_composition_decoupled.py:test_do_generate_uses_context_files, tests/test_tiered_aggregation.py:test_app_controller_do_generate_uses_persona_strategy] diff --git a/src/gui_2.py b/src/gui_2.py index 8329c83d..bdf1bcb0 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -368,12 +368,12 @@ class App: if not name: return preset_files = [] for f in self.context_files: - p = f.path if hasattr(f, 'path') else str(f) - vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' - slc = copy.deepcopy(f.custom_slices) if hasattr(f, 'custom_slices') else [] - msk = copy.deepcopy(f.ast_mask) if hasattr(f, 'ast_mask') else {} - sig = f.ast_signatures if hasattr(f, 'ast_signatures') else False - dfn = f.ast_definitions if hasattr(f, 'ast_definitions') else False + p = f.path + vm = f.view_mode + slc = copy.deepcopy(f.custom_slices) + msk = copy.deepcopy(f.ast_mask) + sig = f.ast_signatures + dfn = f.ast_definitions preset_files.append(models.ContextFileEntry(path=p, view_mode=vm, custom_slices=slc, ast_mask=msk, ast_signatures=sig, ast_definitions=dfn)) preset = models.ContextPreset(name=name, files=preset_files, screenshots=list(self.screenshots)) self.controller.save_context_preset(preset) @@ -839,8 +839,8 @@ class App: max_tokens = self.max_tokens, auto_add_history = self.ui_auto_add_history, disc_entries = copy.deepcopy(self.disc_entries), - files = [f.to_dict() if hasattr(f, 'to_dict') else f for f in self.files], - context_files = [f.to_dict() if hasattr(f, 'to_dict') else f for f in self.context_files], + files = [f.to_dict() for f in self.files], + context_files = [f.to_dict() for f in self.context_files], screenshots = list(self.screenshots) ) @@ -977,8 +977,8 @@ class App: self.context_files = [] for f in preset.files: fi = models.FileItem(path=f.path, view_mode=f.view_mode) - fi.custom_slices = copy.deepcopy(f.custom_slices) if hasattr(f, 'custom_slices') else [] - fi.ast_mask = copy.deepcopy(f.ast_mask) if hasattr(f, 'ast_mask') else {} + fi.custom_slices = copy.deepcopy(f.custom_slices) + fi.ast_mask = copy.deepcopy(f.ast_mask) fi.ast_signatures = getattr(f, 'ast_signatures', False) fi.ast_definitions = getattr(f, 'ast_definitions', False) self.context_files.append(fi) @@ -994,13 +994,13 @@ class App: @property def ui_file_paths(self) -> list[str]: - return [f.path if hasattr(f, 'path') else str(f) for f in self.files] + return [f.path for f in self.files] @ui_file_paths.setter def ui_file_paths(self, paths: list[str]) -> None: sys.stderr.write(f"[DEBUG] Setting ui_file_paths to: {paths}\n") sys.stderr.flush() - old_files = {f.path: f for f in self.files if hasattr(f, 'path')} + old_files = {f.path: f for f in self.files} new_files = [] now = time.time() for p in paths: @@ -1312,7 +1312,7 @@ class App: missing_keys = [] for f in self.context_files: - f_path = f.path if hasattr(f, "path") else str(f) + f_path = f.path mtime = os.path.getmtime(f_path) if os.path.exists(f_path) else 0 cache_key = f"{f_path}_{mtime}" if cache_key not in self._file_stats_cache: missing_keys.append((f_path, cache_key)) @@ -3666,7 +3666,7 @@ def render_files_and_media(app: App) -> None: if imgui.collapsing_header("Files", imgui.TreeNodeFlags_.default_open): with imscope.group(): to_remove_idx = -1 - app.files.sort(key=lambda f: f.path.lower() if hasattr(f, 'path') else str(f).lower()) + app.files.sort(key=lambda f: f.path.lower()) file_indices = {id(f): idx for idx, f in enumerate(app.files)} grouped = aggregate.group_files_by_dir(app.files) if imgui.begin_table("files_table", 3, imgui.TableFlags_.resizable | imgui.TableFlags_.borders | imgui.TableFlags_.row_bg): @@ -3719,12 +3719,12 @@ def render_files_and_media(app: App) -> None: r = hide_tk_root(); paths = filedialog.askopenfilenames(); r.destroy() from src import models for p in paths: - if p not in [f.path if hasattr(f, "path") else f for f in app.files]: app.files.append(models.FileItem(path=p)) + if p not in [f.path for f in app.files]: app.files.append(models.FileItem(path=p)) imgui.same_line() if imgui.button("Add Directory"): r = hide_tk_root(); dirpath = filedialog.askdirectory(); r.destroy() if dirpath: - existing = {f.path if hasattr(f, "path") else str(f) for f in app.files} + existing = {f.path for f in app.files} for root, _dirs, files in os.walk(dirpath): for fname in files: full = os.path.join(root, fname) @@ -3770,12 +3770,12 @@ def render_context_batch_actions(app: App, total_lines: int, total_ast: int) -> for mode in ["full", "summary", "skeleton", "outline", "masked", "none"]: if imgui.button(f"{mode.capitalize()}##batch"): for f in app.context_files: - f_path = f.path if hasattr(f, "path") else str(f) + f_path = f.path if f_path in app.ui_selected_context_files: f.view_mode = mode imgui.same_line() if imgui.button("Sel All##selall"): for f in app.context_files: - f_path = f.path if hasattr(f, "path") else str(f) + f_path = f.path app.ui_selected_context_files.add(f_path) imgui.same_line() if imgui.button("Unsel All##unselall"): app.ui_selected_context_files.clear() @@ -3783,9 +3783,9 @@ def render_context_batch_actions(app: App, total_lines: int, total_ast: int) -> if imgui.button("Add Files##add_btn"): imgui.open_popup("Select Context Files") imgui.same_line() if imgui.button("Add All##addall"): - context_paths = {f.path if hasattr(f, "path") else str(f) for f in app.context_files} + context_paths = {f.path for f in app.context_files} for f in app.files: - f_path = f.path if hasattr(f, "path") else str(f) + f_path = f.path if f_path not in context_paths: f_copy = copy.deepcopy(f) app.context_files.append(f_copy) @@ -3794,7 +3794,7 @@ def render_context_batch_actions(app: App, total_lines: int, total_ast: int) -> if imgui.button("Del##batch"): new_files = [] for f in app.context_files: - f_path = f.path if hasattr(f, "path") else str(f) + f_path = f.path if f_path not in app.ui_selected_context_files: new_files.append(f) app.context_files = new_files app.ui_selected_context_files.clear() @@ -3837,7 +3837,7 @@ def render_add_context_files_modal(app: App) -> None: # Create a temporary selection set if not initialized if not hasattr(app, '_ui_picker_selected'): app._ui_picker_selected = set() for f in app.files: - fpath = f.path if hasattr(f, 'path') else str(f) + fpath = f.path # Skip if already in context if any((cf.path if hasattr(cf, 'path') else str(cf)) == fpath for cf in app.context_files): continue @@ -4364,12 +4364,12 @@ def render_context_presets(app: App) -> None: for f in app.context_files: import copy from src import models - p = f.path if hasattr(f, 'path') else str(f) - vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' - slc = copy.deepcopy(f.custom_slices) if hasattr(f, 'custom_slices') else [] - msk = copy.deepcopy(f.ast_mask) if hasattr(f, 'ast_mask') else {} - sig = f.ast_signatures if hasattr(f, 'ast_signatures') else False - dfn = f.ast_definitions if hasattr(f, 'ast_definitions') else False + p = f.path + vm = f.view_mode + slc = copy.deepcopy(f.custom_slices) + msk = copy.deepcopy(f.ast_mask) + sig = f.ast_signatures + dfn = f.ast_definitions preset_files.append(models.ContextFileEntry(path=p, view_mode=vm, custom_slices=slc, ast_mask=msk, ast_signatures=sig, ast_definitions=dfn)) preset = models.ContextPreset(name=active, files=preset_files, screenshots=list(app.screenshots)) app.controller.save_context_preset(preset) @@ -4390,7 +4390,7 @@ def render_context_presets(app: App) -> None: missing = [] root = app.controller.active_project_root for f in app.context_files: - path = f.path if hasattr(f, "path") else str(f) + path = f.path if not os.path.isabs(path): full_path = os.path.join(root, path) else: full_path = path if not os.path.exists(full_path): missing.append(path) @@ -4404,12 +4404,12 @@ def render_context_presets(app: App) -> None: for f in app.context_files: import copy from src import models - p = f.path if hasattr(f, 'path') else str(f) - vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' - slc = copy.deepcopy(f.custom_slices) if hasattr(f, 'custom_slices') else [] - msk = copy.deepcopy(f.ast_mask) if hasattr(f, 'ast_mask') else {} - sig = f.ast_signatures if hasattr(f, 'ast_signatures') else False - dfn = f.ast_definitions if hasattr(f, 'ast_definitions') else False + p = f.path + vm = f.view_mode + slc = copy.deepcopy(f.custom_slices) + msk = copy.deepcopy(f.ast_mask) + sig = f.ast_signatures + dfn = f.ast_definitions preset_files.append(models.ContextFileEntry(path=p, view_mode=vm, custom_slices=slc, ast_mask=msk, ast_signatures=sig, ast_definitions=dfn)) preset = models.ContextPreset(name=name, files=preset_files, screenshots=list(app.screenshots)) app.controller.save_context_preset(preset) @@ -4539,12 +4539,12 @@ def render_context_modals(app: App) -> None: for f in app.context_files: import copy from src import models - p = f.path if hasattr(f, 'path') else str(f) - vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' - slc = copy.deepcopy(f.custom_slices) if hasattr(f, 'custom_slices') else [] - msk = copy.deepcopy(f.ast_mask) if hasattr(f, 'ast_mask') else {} - sig = f.ast_signatures if hasattr(f, 'ast_signatures') else False - dfn = f.ast_definitions if hasattr(f, 'ast_definitions') else False + p = f.path + vm = f.view_mode + slc = copy.deepcopy(f.custom_slices) + msk = copy.deepcopy(f.ast_mask) + sig = f.ast_signatures + dfn = f.ast_definitions preset_files.append(models.ContextFileEntry(path=p, view_mode=vm, custom_slices=slc, ast_mask=msk, ast_signatures=sig, ast_definitions=dfn)) preset = models.ContextPreset(name=name, files=preset_files, screenshots=list(app.screenshots)) app.controller.save_context_preset(preset) @@ -4562,9 +4562,9 @@ def render_context_modals(app: App) -> None: def _get_context_composition_state(app: App) -> tuple: files_state = [] for f in app.context_files: - p = f.path if hasattr(f, 'path') else str(f) - vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' - agg = f.auto_aggregate if hasattr(f, 'auto_aggregate') else False + p = f.path + vm = f.view_mode + agg = f.auto_aggregate slc = tuple((s.get('start_line'), s.get('end_line'), s.get('tag'), s.get('comment')) for s in getattr(f, 'custom_slices', [])) mask = tuple(sorted(getattr(f, 'ast_mask', {}).items())) files_state.append((p, vm, agg, slc, mask))