Fix Alembic migration import error in containerized environment
This commit is contained in:
parent
da0fe5a40e
commit
a1c3bee298
@ -1,11 +1,19 @@
|
||||
"""
|
||||
Alembic environment script for database migrations
|
||||
"""
|
||||
import sys
|
||||
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()
|
||||
|
||||
# this is the Alembic Config object, which provides
|
||||
# access to the values within the .ini file in use.
|
||||
config = context.config
|
||||
@ -15,10 +23,43 @@ config = context.config
|
||||
if config.config_file_name is not None:
|
||||
fileConfig(config.config_file_name)
|
||||
|
||||
# add your model's MetaData object here
|
||||
# for 'autogenerate' support
|
||||
from app.models import Todo # noqa
|
||||
from app.core.database import Base # noqa
|
||||
# Try different import strategies to handle various deployment environments
|
||||
try:
|
||||
# Standard import approach
|
||||
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
|
||||
|
||||
|
29
alembic/find_modules.py
Normal file
29
alembic/find_modules.py
Normal 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
50
test_imports.py
Normal 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.")
|
Loading…
x
Reference in New Issue
Block a user