| |
| """ |
| AST-based auto-fix script for indentation errors in Atom backend. |
| |
| This script uses the tokenize module to precisely fix indentation issues |
| where `with get_db_session() as db:` is followed by an incorrectly indented `try:` block. |
| """ |
|
|
| import io |
| import os |
| from pathlib import Path |
| import sys |
| import tokenize |
| from typing import List, Tuple |
|
|
| |
| BACKEND_DIR = Path("/Users/rushiparikh/projects/atom/backend") |
|
|
|
|
| def fix_file_tokens(filepath: Path) -> Tuple[bool, str]: |
| """ |
| Fix indentation issues using token-level processing. |
| Returns (success, message) |
| """ |
| try: |
| with open(filepath, 'rb') as f: |
| tokens = list(tokenize.tokenize(f.readline)) |
|
|
| |
| result_tokens = [] |
| i = 0 |
|
|
| while i < len(tokens): |
| token = tokens[i] |
|
|
| |
| |
| if token.type == tokenize.NAME and token.string == 'with': |
| |
| j = i |
| found_get_db_session = False |
| found_try_at_wrong_indent = False |
|
|
| |
| while j < len(tokens) and tokens[j].type != tokenize.NEWLINE: |
| if tokens[j].type == tokenize.NAME and tokens[j].string == 'get_db_session': |
| found_get_db_session = True |
| j += 1 |
|
|
| if found_get_db_session: |
| |
| |
| while j < len(tokens) and tokens[j].type in (tokenize.NEWLINE, tokenize.NL, tokenize.COMMENT): |
| j += 1 |
|
|
| |
| if j < len(tokens) and tokens[j].type == tokenize.NAME and tokens[j].string == 'try': |
| |
| with_indent = tokens[i].start[1] |
| try_indent = tokens[j].start[1] |
|
|
| if try_indent <= with_indent + 1: |
| |
| |
| new_start = (tokens[j].start[0], with_indent + 4) |
| if tokens[j].end[1] == tokens[j].start[1]: |
| new_end = (tokens[j].end[0], with_indent + 4 + len(tokens[j].string)) |
| else: |
| new_end = tokens[j].end |
| new_end = (new_end[0], new_end[1] + (with_indent + 4 - try_indent)) |
|
|
| fixed_token = tokenize.TokenInfo( |
| type=tokens[j].type, |
| string=tokens[j].string, |
| start=new_start, |
| end=new_end, |
| line=tokens[j].line |
| ) |
| result_tokens.append(fixed_token) |
| i = j + 1 |
| continue |
|
|
| result_tokens.append(token) |
| i += 1 |
|
|
| |
| source_lines = [] |
| current_line = 1 |
| current_col = 0 |
|
|
| for token in result_tokens: |
| if token.type == tokenize.ENCODING: |
| continue |
|
|
| |
| while current_line < token.start[0]: |
| source_lines.append('\n') |
| current_line += 1 |
| current_col = 0 |
|
|
| |
| while current_col < token.start[1]: |
| source_lines.append(' ') |
| current_col += 1 |
|
|
| |
| if token.type != tokenize.NEWLINE and token.type != tokenize.NL: |
| source_lines.append(token.string) |
| current_col += len(token.string) |
| else: |
| source_lines.append('\n') |
| current_line += 1 |
| current_col = 0 |
|
|
| |
| fixed_content = ''.join(source_lines) |
|
|
| with open(filepath, 'w') as f: |
| f.write(fixed_content) |
|
|
| return True, "Fixed indentation" |
|
|
| except Exception as e: |
| return False, f"Error: {str(e)}" |
|
|
|
|
| def fix_simple_pattern(filepath: Path) -> bool: |
| """ |
| Simple line-based fix for the specific pattern. |
| """ |
| try: |
| with open(filepath, 'r') as f: |
| lines = f.readlines() |
|
|
| new_lines = [] |
| i = 0 |
| fixes = 0 |
|
|
| while i < len(lines): |
| line = lines[i] |
|
|
| |
| if 'with get_db_session() as db:' in line: |
| |
| indent = len(line) - len(line.lstrip()) |
| new_lines.append(line) |
| i += 1 |
|
|
| |
| if i < len(lines): |
| next_line = lines[i] |
| next_indent = len(next_line) - len(next_line.lstrip()) |
|
|
| |
| if 'try:' in next_line and next_indent <= indent + 1: |
| |
| fixed_try = ' ' * (indent + 4) + 'try:' + '\n' |
| new_lines.append(fixed_try) |
| fixes += 1 |
| i += 1 |
|
|
| |
| while i < len(lines): |
| new_lines.append(lines[i]) |
| i += 1 |
| break |
|
|
| new_lines.append(line) |
| i += 1 |
|
|
| if fixes > 0: |
| with open(filepath, 'w') as f: |
| f.writelines(new_lines) |
| return True |
|
|
| return False |
|
|
| except Exception as e: |
| print(f" ✗ Error: {e}") |
| return False |
|
|
|
|
| def scan_and_fix(): |
| """Scan all Python files and fix indentation errors.""" |
| print("=" * 70) |
| print("Auto-fixing indentation errors in Atom backend") |
| print("=" * 70) |
| print() |
|
|
| |
| problematic_files = [ |
| "core/business_agents.py", |
| "core/chat_session_manager.py", |
| "core/change_order_agent.py", |
| "core/communication_service.py", |
| "core/workflow_engine.py", |
| "core/resource_manager.py", |
| "core/atom_meta_agent.py", |
| "core/lifecycle_comm_generator.py", |
| "core/background_agent_runner.py", |
| "core/admin_bootstrap.py", |
| "core/formula_memory.py", |
| "core/uptime_tracker.py", |
| "core/scheduler.py", |
| "core/llm/byok_handler.py", |
| "core/archive/database_v1.py", |
| "integrations/chat_orchestrator.py", |
| "integrations/universal_webhook_bridge.py", |
| "integrations/zoho_workdrive_service.py", |
| ] |
|
|
| fixed_count = 0 |
| for rel_path in problematic_files: |
| filepath = BACKEND_DIR / rel_path |
| if not filepath.exists(): |
| continue |
|
|
| print(f"🔧 {rel_path}") |
|
|
| if fix_simple_pattern(filepath): |
| print(f" ✓ Fixed") |
| fixed_count += 1 |
| else: |
| print(f" (no fix needed or failed)") |
| print() |
|
|
| print("=" * 70) |
| print(f"Fixed {fixed_count} files") |
| print("=" * 70) |
| print() |
|
|
| |
| import ast |
| print("Verifying fixes...") |
| remaining = 0 |
| for rel_path in problematic_files: |
| filepath = BACKEND_DIR / rel_path |
| if not filepath.exists(): |
| continue |
|
|
| try: |
| with open(filepath, 'r') as f: |
| content = f.read() |
| ast.parse(content) |
| except (SyntaxError, IndentationError) as e: |
| print(f" ✗ {rel_path}:{e.lineno} - {e.msg}") |
| remaining += 1 |
|
|
| if remaining == 0: |
| print("✅ All files fixed successfully!") |
| return 0 |
| else: |
| print(f"⚠️ {remaining} files still have errors") |
| return 1 |
|
|
|
|
| if __name__ == '__main__': |
| sys.exit(scan_and_fix()) |
|
|