annator-atom / backend /scripts /fix_db_sessions.py
techprotrade's picture
Full stack ATOM backend + AIMONEYFLOW clients (port 7860) (part 5)
f84a02d verified
Raw
History Blame Contribute Delete
6.12 kB
#!/usr/bin/env python3
"""
Database Session Auto-Fixer
Automatically fixes common database session management patterns.
"""
import os
import re
from typing import List, Tuple
def fix_session_management(content: str) -> Tuple[str, int]:
"""
Fix database session management patterns in a file.
Returns (fixed_content, number_of_changes)
"""
changes = 0
lines = content.split('\n')
fixed_lines = []
i = 0
while i < len(lines):
line = lines[i]
original_line = line
# Pattern 1: db = SessionLocal() followed by try/finally
if re.search(r'(\w+)\s*=\s*SessionLocal\(\)', line):
indent = len(line) - len(line.lstrip())
var_name = re.search(r'(\w+)\s*=\s*SessionLocal\(\)', line).group(1)
# Check if next lines have try/finally pattern
if i + 1 < len(lines) and 'try:' in lines[i + 1]:
# Skip the db = SessionLocal() line
i += 1 # Move to try:
fixed_lines.append(lines[i]) # Keep try:
# Replace with with get_db_session() pattern
new_indent = ' ' * indent
fixed_lines.append(f'{new_indent}from core.database import get_db_session')
fixed_lines.append(f'{new_indent}')
fixed_lines.append(f'{new_indent}with get_db_session() as {var_name}:')
changes += 1
i += 1
continue
# Pattern 2: with SessionLocal() as db:
if re.search(r'with\s+SessionLocal\(\)\s+as\s+(\w+):', line):
var_name = re.search(r'with\s+SessionLocal\(\)\s+as\s+(\w+):', line).group(1)
line = re.sub(r'with\s+SessionLocal\(\)\s+as\s+(\w+):',
f'with get_db_session() as {var_name}:', line)
changes += 1
# Pattern 3: Remove manual db.close() in with blocks
if re.search(rf'{var_name}\.close\(\)' if 'var_name' in locals() else r'\w+\.close\(\)', line):
# Only remove if it's in a finally block
if 'finally:' in lines[i-1] if i > 0 else False:
line = '#' + line + ' # Removed: context manager handles cleanup'
changes += 1
# Pattern 4: Remove manual db.commit() at end of with block
# (context manager auto-commits on success)
# We'll leave this for manual review as it's context-dependent
fixed_lines.append(line)
i += 1
return '\n'.join(fixed_lines), changes
def add_get_db_import(content: str) -> str:
"""Add get_db_session import if not present."""
if 'from core.database import get_db_session' in content:
return content
# Find existing database import
if 'from core.database import' in content:
# Add to existing import
content = re.sub(
r'from core\.database import ([^\n]+)',
r'from core.database import \1, get_db_session',
content
)
else:
# Add new import after imports
lines = content.split('\n')
import_idx = 0
for i, line in enumerate(lines):
if line.startswith('from ') or line.startswith('import '):
import_idx = i + 1
elif import_idx > 0 and not line.startswith('from ') and not line.startswith('import '):
break
lines.insert(import_idx, 'from core.database import get_db_session')
content = '\n'.join(lines)
return content
def fix_file(file_path: str, dry_run: bool = True) -> Tuple[bool, int]:
"""
Fix a single file.
Returns (success, number_of_changes)
"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
original_content = f.read()
fixed_content, changes = fix_session_management(original_content)
if changes > 0:
# Add import if needed
if 'get_db_session' in fixed_content:
fixed_content = add_get_db_import(fixed_content)
if not dry_run:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(fixed_content)
return True, changes
return False, 0
except Exception as e:
print(f" ❌ Error: {e}")
return False, 0
def main():
import argparse
parser = argparse.ArgumentParser(description='Auto-fix database session management')
parser.add_argument('--file', help='File to fix')
parser.add_argument('--list', help='File with list of files to fix')
parser.add_argument('--dry-run', action='store_true', default=True,
help='Show changes without applying (default: True)')
parser.add_argument('--apply', action='store_true',
help='Actually apply changes (disables dry-run)')
args = parser.parse_args()
if args.apply:
args.dry_run = False
files_to_fix = []
if args.file:
files_to_fix.append(args.file)
elif args.list:
with open(args.list, 'r') as f:
files_to_fix = [line.strip() for line in f if line.strip()]
else:
print("Usage: python fix_db_sessions.py --file <file> or --list <file>")
return
mode = "DRY RUN" if args.dry_run else "APPLY"
print(f"Mode: {mode}")
print(f"Files to fix: {len(files_to_fix)}")
print()
total_changes = 0
success_count = 0
for file_path in files_to_fix:
if not os.path.exists(file_path):
print(f"⚠️ File not found: {file_path}")
continue
print(f"Processing: {file_path}")
success, changes = fix_file(file_path, args.dry_run)
if success:
print(f" ✅ {changes} changes")
total_changes += changes
success_count += 1
else:
print(f" ℹ️ No changes needed")
print()
print(f"Summary: {success_count} files, {total_changes} changes")
if args.dry_run:
print("⚠️ DRY RUN MODE - No files were modified")
print("Use --apply to actually apply changes")
if __name__ == '__main__':
main()