Spaces:
				
			
			
	
			
			
					
		Running
		
	
	
	
			
			
	
	
	
	
		
		
					
		Running
		
	File size: 5,390 Bytes
			
			| 3cf9fa0 09ecaf7 4117d7e 3cf9fa0 09ecaf7 4117d7e 0367c22 bc8e3e9 0367c22 bc8e3e9 0367c22 bc8e3e9 09ecaf7 4117d7e 3cf9fa0 4117d7e 3cf9fa0 4117d7e 3cf9fa0 0367c22 bc8e3e9 3cf9fa0 0367c22 4117d7e bc8e3e9 0367c22 4117d7e 09ecaf7 4117d7e 09ecaf7 4117d7e 09ecaf7 4117d7e 0367c22 bc8e3e9 0367c22 3cf9fa0 bc8e3e9 4117d7e 0367c22 bc8e3e9 0367c22 bc8e3e9 0367c22 bc8e3e9 0367c22 bc8e3e9 0367c22 bc8e3e9 0367c22 09ecaf7 4117d7e 09ecaf7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | # ---- ensure .env is loaded for alembic too ----
from pathlib import Path
try:
    from dotenv import load_dotenv
    # Use utf-8-sig to strip BOM just in case
    load_dotenv(dotenv_path=Path(__file__).resolve().parents[1] / ".env",
                override=True, encoding="utf-8-sig")
except Exception:
    pass
# -----------------------------------------------
import os
import sys
from dotenv import load_dotenv
# Set environment encoding to handle Windows encoding issues
if sys.platform == "win32":
    import locale
    try:
        # Try to set UTF-8 encoding for environment variables
        os.environ['PYTHONIOENCODING'] = 'utf-8'
    except:
        pass
env_path = os.path.join(os.path.dirname(__file__), '..', '.env')
print(f"Looking for .env file at: {env_path}")
print(f".env file exists: {os.path.exists(env_path)}")
if os.path.exists(env_path):
    load_dotenv(env_path, encoding="utf-8-sig")
    print("SUCCESS: Loaded .env file from py_backend directory")
else:
    print("ERROR: .env file not found in py_backend directory")
    # Try current directory
    load_dotenv(encoding="utf-8-sig")
    print("INFO: Attempted to load .env from current directory")
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from alembic import context
from sqlalchemy import create_engine, pool
try:
    from app.models import Base
    target_metadata = Base.metadata
    print("Successfully imported models from app.models")
except ImportError as e:
    print(f"Could not import app.models: {e}")
    print(f"Current working directory: {os.getcwd()}")
    print(f"Python path: {sys.path}")
    from sqlalchemy import MetaData
    target_metadata = MetaData()
    print("Using fallback metadata - migrations may not work properly")
config = context.config
target_metadata = Base.metadata
def _get_db_url() -> str:
    """
    Prefer a dedicated migration URL; otherwise use the app URL.
    Only adds sslmode=require for remote connections (not localhost).
    """
    # Debug: Environment variables loaded
    print("Environment variables loaded")
    
    url = os.getenv("ALEMBIC_DATABASE_URL") or os.getenv("DATABASE_URL")
    if not url:
        print("No DATABASE_URL found in environment")
        raise RuntimeError("Set ALEMBIC_DATABASE_URL or DATABASE_URL for Alembic migrations.")
    # Clean the URL to remove any problematic characters (fallback for edge cases)
    try:
        # Test if the URL can be used for connection
        url.encode('utf-8').decode('utf-8')
    except UnicodeError:
        print("WARNING: Encoding issue detected in database URL, attempting to clean...")
        # Replace common problematic characters
        url = url.replace('"', '"').replace('"', '"')  # Smart quotes
        url = url.replace(''', "'").replace(''', "'")  # Smart apostrophes
        url = url.replace('β', '-').replace('β', '-')  # En/em dashes
        # Remove any non-ASCII characters
        url = ''.join(char for char in url if ord(char) < 128)
        print("Cleaned URL: [HIDDEN]")
    print("Alembic database URL: [HIDDEN]")
    
    if url.startswith("psql '") and url.endswith("'"):
        url = url[6:-1]
        print("Cleaned URL: [HIDDEN]")
    if "sslmode=" not in url and "localhost" not in url and "127.0.0.1" not in url:
        url = f"{url}{'&' if '?' in url else '?'}sslmode=require"
        print(f"Added sslmode: {url}")
    
    return url
def run_migrations_offline() -> None:
    """Run migrations in 'offline' mode."""
    url = _get_db_url()
    context.configure(
        url=url,
        target_metadata=target_metadata,
        literal_binds=True,
        dialect_opts={"paramstyle": "named"},
        compare_type=True,
        compare_server_default=True,
    )
    with context.begin_transaction():
        context.run_migrations()
def run_migrations_online() -> None:
    """Run migrations in 'online' mode."""
    try:
        url = _get_db_url()
        print(f"Creating engine with URL: {url}")
        
        # Add encoding parameters to handle Windows encoding issues
        engine_kwargs = {
            'poolclass': pool.NullPool,
            'future': True,
        }
        
        # For PostgreSQL connections, add encoding parameters
        if url.startswith('postgresql://'):
            engine_kwargs['connect_args'] = {
                'client_encoding': 'utf8',
                'options': '-c client_encoding=utf8'
            }
        
        connectable = create_engine(url, **engine_kwargs)
        print("Engine created successfully")
        with connectable.connect() as connection:
            print("Database connection established")
            context.configure(
                connection=connection,
                target_metadata=target_metadata,
                compare_type=True,
                compare_server_default=True,
            )
            with context.begin_transaction():
                print("Running migrations...")
                context.run_migrations()
                print("Migrations completed successfully")
    except Exception as e:
        print(f"Migration failed: {e}")
        print(f"Error type: {type(e).__name__}")
        import traceback
        print(f"Full traceback: {traceback.format_exc()}")
        raise
if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()
 | 
