From 381c0e2b50d67971452f8c40287d008b3e72ee5e Mon Sep 17 00:00:00 2001 From: LemonNexus Date: Wed, 11 Feb 2026 13:00:10 +0000 Subject: [PATCH] fix: template and session loading - convert rows to lists before accessing - Convert sqlite3.Row to list before accessing by index - Add detailed debug logging for troubleshooting - Fix fromisoformat error by checking for None values - Add try/except around each row to skip bad data --- ui/main_window.py | 140 ++++++++++++++++++++++++++++++---------------- 1 file changed, 92 insertions(+), 48 deletions(-) diff --git a/ui/main_window.py b/ui/main_window.py index 674a8e8..00d6b47 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -1135,46 +1135,65 @@ class MainWindow(QMainWindow): "SELECT id, name, type, created_at, description FROM projects ORDER BY name" ) - for proj in projects: + self.log_debug("Templates", f"Raw query returned {len(projects)} rows") + + for i, proj in enumerate(projects): try: - # Access row data by index to avoid key issues - proj_id = proj[0] if len(proj) > 0 else 0 - proj_name = proj[1] if len(proj) > 1 else "Unnamed" - proj_type = proj[2] if len(proj) > 2 else 'hunt' - proj_created = proj[3] if len(proj) > 3 else None - proj_desc = proj[4] if len(proj) > 4 else '' + # Log what we're working with for debugging + self.log_debug("Templates", f"Row {i}: type={type(proj)}, len={len(proj) if hasattr(proj, '__len__') else 'N/A'}") + # Convert row to tuple/list if it's a sqlite3.Row + if hasattr(proj, '__iter__') and not isinstance(proj, (str, bytes)): + row_data = list(proj) + else: + row_data = [proj] + + self.log_debug("Templates", f"Row {i} data: {row_data}") + + # Safely extract values + proj_id = int(row_data[0]) if len(row_data) > 0 else 0 + proj_name = str(row_data[1]) if len(row_data) > 1 else "Unnamed" + proj_type = str(row_data[2]) if len(row_data) > 2 else 'hunt' + proj_created = row_data[3] if len(row_data) > 3 else None + proj_desc = str(row_data[4]) if len(row_data) > 4 else '' + + self.log_debug("Templates", f"Extracted: id={proj_id}, name={proj_name}, type={proj_type}") + + # Convert activity type activity = ActivityType.from_string(proj_type) # Get session count session_count = 0 try: count_result = self.db.fetchone( - "SELECT COUNT(*) as count FROM sessions WHERE project_id = ?", + "SELECT COUNT(*) FROM sessions WHERE project_id = ?", (proj_id,) ) - if count_result and len(count_result) > 0: - session_count = count_result[0] - except: - pass + if count_result: + count_data = list(count_result) + session_count = int(count_data[0]) if len(count_data) > 0 else 0 + except Exception as e: + self.log_debug("Templates", f"Count query failed: {e}") # Get last session last_session = None try: last_result = self.db.fetchone( - "SELECT MAX(started_at) as last FROM sessions WHERE project_id = ?", + "SELECT MAX(started_at) FROM sessions WHERE project_id = ?", (proj_id,) ) - if last_result and len(last_result) > 0 and last_result[0]: - last_session = datetime.fromisoformat(last_result[0]) - except: - pass + if last_result: + last_data = list(last_result) + if len(last_data) > 0 and last_data[0]: + last_session = datetime.fromisoformat(str(last_data[0])) + except Exception as e: + self.log_debug("Templates", f"Last session query failed: {e}") # Parse created_at created_at = None if proj_created: try: - created_at = datetime.fromisoformat(proj_created) + created_at = datetime.fromisoformat(str(proj_created)) except: pass @@ -1188,9 +1207,12 @@ class MainWindow(QMainWindow): last_session=last_session ) templates.append(template) + self.log_debug("Templates", f"Added template: {proj_name}") except Exception as row_error: - self.log_warning("Templates", f"Skipping malformed template row: {row_error}") + self.log_warning("Templates", f"Skipping row {i}: {row_error}") + import traceback + logger.error(traceback.format_exc()) continue except Exception as e: @@ -1302,37 +1324,59 @@ class MainWindow(QMainWindow): """) for row in rows: - # sqlite3.Row doesn't have .get() method, use direct access - row_type = row['type'] if 'type' in row.keys() else 'hunt' - activity = ActivityType.from_string(row_type) - - # Calculate duration - started = datetime.fromisoformat(row['started_at']) - duration = 0 - ended_at = row['ended_at'] if 'ended_at' in row.keys() else None - if ended_at: - ended = datetime.fromisoformat(ended_at) - duration = int((ended - started).total_seconds() / 60) - elif row['status'] == 'running': - duration = int((datetime.now() - started).total_seconds() / 60) - - # Get costs (placeholder - would need actual cost tracking) - total_cost = 0.0 - total_return = 0.0 - - session = RecentSession( - id=row['id'], - template_name=row['template_name'], - activity_type=activity, - started_at=started, - duration_minutes=duration, - total_cost=total_cost, - total_return=total_return, - status=row['status'] if 'status' in row.keys() else 'unknown' - ) - sessions.append(session) + try: + # Convert row to list for safe access + row_data = list(row) + + # Safely extract values by index + session_id = int(row_data[0]) if len(row_data) > 0 else 0 + template_name = str(row_data[1]) if len(row_data) > 1 else "Unknown" + row_type = str(row_data[2]) if len(row_data) > 2 else 'hunt' + started_at_str = row_data[3] if len(row_data) > 3 else None + ended_at_str = row_data[4] if len(row_data) > 4 else None + status = str(row_data[5]) if len(row_data) > 5 else 'unknown' + + activity = ActivityType.from_string(row_type) + + # Parse started_at + started = None + if started_at_str: + started = datetime.fromisoformat(str(started_at_str)) + else: + started = datetime.now() + + # Calculate duration + duration = 0 + if ended_at_str: + ended = datetime.fromisoformat(str(ended_at_str)) + duration = int((ended - started).total_seconds() / 60) + elif status == 'running': + duration = int((datetime.now() - started).total_seconds() / 60) + + # Get costs (placeholder - would need actual cost tracking) + total_cost = 0.0 + total_return = 0.0 + + session = RecentSession( + id=session_id, + template_name=template_name, + activity_type=activity, + started_at=started, + duration_minutes=duration, + total_cost=total_cost, + total_return=total_return, + status=status + ) + sessions.append(session) + + except Exception as row_error: + self.log_warning("Sessions", f"Skipping malformed session row: {row_error}") + continue + except Exception as e: self.log_error("Sessions", f"Failed to load sessions: {e}") + import traceback + logger.error(traceback.format_exc()) return sessions