Fix Alembic migration import error in containerized environment
This commit is contained in:
parent
a1c3bee298
commit
522284ce84
@ -6,13 +6,25 @@ from logging.config import fileConfig
|
||||
from pathlib import Path
|
||||
|
||||
from alembic import context
|
||||
|
||||
# Custom module to help with finding modules in containerized environments
|
||||
from alembic.find_modules import setup_python_path
|
||||
from sqlalchemy import engine_from_config, pool
|
||||
|
||||
# Setup Python path to find app modules in various environments
|
||||
setup_python_path()
|
||||
# Get the directory where this script is located
|
||||
current_dir = Path(__file__).resolve().parent
|
||||
|
||||
# Import our custom module for path setup
|
||||
sys.path.insert(0, str(current_dir))
|
||||
try:
|
||||
from find_modules import setup_python_path
|
||||
# Setup Python path to find app modules in various environments
|
||||
setup_python_path()
|
||||
except ImportError:
|
||||
# Fallback for direct path setup if the module can't be imported
|
||||
project_root = current_dir.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
# Check if we're in a Docker container with code mounted at /app/repo
|
||||
repo_path = Path('/app/repo')
|
||||
if repo_path.exists():
|
||||
sys.path.insert(0, str(repo_path))
|
||||
|
||||
# this is the Alembic Config object, which provides
|
||||
# access to the values within the .ini file in use.
|
||||
@ -32,7 +44,6 @@ except ImportError:
|
||||
try:
|
||||
# Path-based import for some container setups
|
||||
import importlib.util
|
||||
import sys
|
||||
|
||||
# Try to find the module file
|
||||
for base_path in sys.path:
|
||||
@ -55,7 +66,26 @@ except ImportError:
|
||||
Base = getattr(db_module, "Base")
|
||||
break
|
||||
else:
|
||||
raise ImportError("Could not find app modules in any path")
|
||||
# Try to find modules in the container-specific location
|
||||
model_path = Path('/app/repo/app/models/todo.py')
|
||||
db_path = Path('/app/repo/app/core/database.py')
|
||||
|
||||
if model_path.exists() and db_path.exists():
|
||||
# Load the todo module
|
||||
spec = importlib.util.spec_from_file_location("todo", model_path)
|
||||
todo_module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(todo_module)
|
||||
|
||||
# Load the database module
|
||||
spec = importlib.util.spec_from_file_location("database", db_path)
|
||||
db_module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(db_module)
|
||||
|
||||
# Get the required objects
|
||||
Todo = getattr(todo_module, "Todo")
|
||||
Base = getattr(db_module, "Base")
|
||||
else:
|
||||
raise ImportError("Could not find app modules in any path")
|
||||
except Exception as e:
|
||||
print(f"Error importing models: {e}")
|
||||
print(f"Current sys.path: {sys.path}")
|
||||
|
@ -20,10 +20,54 @@ def setup_python_path():
|
||||
if str(project_root) not in sys.path:
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
# Check if we're in a Docker container with code mounted at /app/repo
|
||||
repo_path = Path('/app/repo')
|
||||
if repo_path.exists() and str(repo_path) not in sys.path:
|
||||
sys.path.insert(0, str(repo_path))
|
||||
# Container environments often mount code in specific locations
|
||||
# Check multiple possible locations
|
||||
possible_repo_paths = [
|
||||
Path('/app/repo'), # Common Kubernetes/Docker path
|
||||
Path('/app'), # Another common Docker path
|
||||
Path('/projects/simpletodoapp-ayt143') # Local development path
|
||||
]
|
||||
|
||||
# Add all existing paths to sys.path
|
||||
for repo_path in possible_repo_paths:
|
||||
if repo_path.exists() and str(repo_path) not in sys.path:
|
||||
sys.path.insert(0, str(repo_path))
|
||||
|
||||
# Debug information to help troubleshoot path issues
|
||||
print(f"Python sys.path configured as: {sys.path}")
|
||||
|
||||
# Return the actual Python paths used, for debugging
|
||||
return sys.path
|
||||
|
||||
|
||||
def find_module_path(module_name, possible_paths=None):
|
||||
"""
|
||||
Try to find a module by checking multiple possible locations.
|
||||
Returns the full path to the module if found, None otherwise.
|
||||
|
||||
Args:
|
||||
module_name: Name of the module to find (e.g. 'app.models.todo')
|
||||
possible_paths: List of base paths to check
|
||||
|
||||
Returns:
|
||||
Path object if module found, None otherwise
|
||||
"""
|
||||
if possible_paths is None:
|
||||
possible_paths = sys.path
|
||||
|
||||
module_parts = module_name.split('.')
|
||||
|
||||
for base_path in possible_paths:
|
||||
path = Path(base_path)
|
||||
for part in module_parts:
|
||||
path = path / part
|
||||
|
||||
py_path = path.with_suffix('.py')
|
||||
init_path = path / '__init__.py'
|
||||
|
||||
if py_path.exists():
|
||||
return py_path
|
||||
elif init_path.exists():
|
||||
return init_path
|
||||
|
||||
return None
|
||||
|
55
test_migrations.py
Normal file
55
test_migrations.py
Normal file
@ -0,0 +1,55 @@
|
||||
"""
|
||||
Test script to verify that Alembic migrations will work in the container environment.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
print(f"Current working directory: {os.getcwd()}")
|
||||
print(f"Initial Python path: {sys.path}")
|
||||
|
||||
# Simulate the container environment where alembic is executed
|
||||
repo_dir = Path('/app/repo')
|
||||
if not repo_dir.exists():
|
||||
print(f"Simulating the /app/repo directory structure (not found on disk)")
|
||||
# Just for testing, we'll use the current directory
|
||||
repo_dir = Path(os.getcwd())
|
||||
|
||||
# Get paths for important files
|
||||
alembic_dir = repo_dir / 'alembic'
|
||||
env_py = alembic_dir / 'env.py'
|
||||
find_modules_py = alembic_dir / 'find_modules.py'
|
||||
|
||||
print(f"Alembic directory: {alembic_dir}")
|
||||
print(f"env.py exists: {env_py.exists()}")
|
||||
print(f"find_modules.py exists: {find_modules_py.exists()}")
|
||||
|
||||
# Add alembic directory to Python path
|
||||
if str(alembic_dir) not in sys.path:
|
||||
sys.path.insert(0, str(alembic_dir))
|
||||
print(f"Added alembic directory to sys.path: {sys.path}")
|
||||
|
||||
# Try to import our module
|
||||
try:
|
||||
from find_modules import setup_python_path
|
||||
print(f"Successfully imported setup_python_path from find_modules")
|
||||
|
||||
# Try to set up the Python path
|
||||
paths = setup_python_path()
|
||||
print(f"Updated Python path: {paths}")
|
||||
|
||||
# Try to import our models
|
||||
try:
|
||||
from app.models import Todo
|
||||
print(f"Successfully imported Todo model: {Todo}")
|
||||
|
||||
from app.core.database import Base
|
||||
print(f"Successfully imported Base from database module: {Base}")
|
||||
|
||||
print("Migration imports should work correctly!")
|
||||
except ImportError as e:
|
||||
print(f"Error importing app modules: {e}")
|
||||
print("You may need to run this script from the project root directory.")
|
||||
except ImportError as e:
|
||||
print(f"Error importing find_modules: {e}")
|
||||
print("Make sure you're running this script from the project root directory.")
|
Loading…
x
Reference in New Issue
Block a user