Fix Alembic migration import error in containerized environment

This commit is contained in:
Automated Action 2025-05-19 01:03:25 +00:00
parent da0fe5a40e
commit a1c3bee298
3 changed files with 124 additions and 4 deletions

View File

@ -1,11 +1,19 @@
""" """
Alembic environment script for database migrations Alembic environment script for database migrations
""" """
import sys
from logging.config import fileConfig from logging.config import fileConfig
from pathlib import Path
from alembic import context 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 from sqlalchemy import engine_from_config, pool
# Setup Python path to find app modules in various environments
setup_python_path()
# this is the Alembic Config object, which provides # this is the Alembic Config object, which provides
# access to the values within the .ini file in use. # access to the values within the .ini file in use.
config = context.config config = context.config
@ -15,10 +23,43 @@ config = context.config
if config.config_file_name is not None: if config.config_file_name is not None:
fileConfig(config.config_file_name) fileConfig(config.config_file_name)
# add your model's MetaData object here # Try different import strategies to handle various deployment environments
# for 'autogenerate' support try:
from app.models import Todo # noqa # Standard import approach
from app.core.database import Base # noqa from app.models import Todo # noqa
from app.core.database import Base # noqa
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:
model_path = Path(base_path) / "app" / "models" / "todo.py"
db_path = Path(base_path) / "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")
break
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}")
raise
target_metadata = Base.metadata target_metadata = Base.metadata

29
alembic/find_modules.py Normal file
View File

@ -0,0 +1,29 @@
"""
Module finder helper for Alembic migrations in containerized environments.
"""
import sys
from pathlib import Path
def setup_python_path():
"""
Add necessary paths to Python's sys.path to make imports work
in various environments including Docker containers
"""
# Get the directory where this script is located
current_dir = Path(__file__).resolve().parent
# The project root is one level up from the 'alembic' directory
project_root = current_dir.parent
# Add the project root to the Python path if it's not already there
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))
# Return the actual Python paths used, for debugging
return sys.path

50
test_imports.py Normal file
View File

@ -0,0 +1,50 @@
"""
Test script to verify imports work correctly.
This can be run both locally and in the container to verify the setup.
"""
import os
import sys
# Print current working directory
print(f"Current working directory: {os.getcwd()}")
# Print Python path
print(f"Python path: {sys.path}")
# Try to import the app modules
try:
# Add current directory to path
sys.path.insert(0, os.getcwd())
# Try importing the models
from app.models import Todo
print(f"Successfully imported Todo from app.models: {Todo}")
from app.core.database import Base
print(f"Successfully imported Base from app.core.database: {Base}")
print("All imports succeeded!")
except Exception as e:
print(f"Error importing modules: {e}")
# Try a different approach for containerized environments
try:
# Try to execute the find_modules code
sys.path.insert(0, os.path.join(os.getcwd(), 'alembic'))
from find_modules import setup_python_path
# Setup paths
paths = setup_python_path()
print(f"Updated paths: {paths}")
# Try importing again
from app.models import Todo
print(f"Successfully imported Todo after path setup: {Todo}")
from app.core.database import Base
print(f"Successfully imported Base after path setup: {Base}")
print("Imports succeeded after path setup!")
except Exception as inner_e:
print(f"Still failed after path setup: {inner_e}")
print("This might indicate a deeper issue with the module structure.")