From a1c3bee29882a84f5d8b6f5bc27aa9a6fe00fc13 Mon Sep 17 00:00:00 2001 From: Automated Action Date: Mon, 19 May 2025 01:03:25 +0000 Subject: [PATCH] Fix Alembic migration import error in containerized environment --- alembic/env.py | 49 ++++++++++++++++++++++++++++++++++++---- alembic/find_modules.py | 29 ++++++++++++++++++++++++ test_imports.py | 50 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 alembic/find_modules.py create mode 100644 test_imports.py diff --git a/alembic/env.py b/alembic/env.py index f9847a8..8b10b6e 100644 --- a/alembic/env.py +++ b/alembic/env.py @@ -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 diff --git a/alembic/find_modules.py b/alembic/find_modules.py new file mode 100644 index 0000000..5a4445c --- /dev/null +++ b/alembic/find_modules.py @@ -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 diff --git a/test_imports.py b/test_imports.py new file mode 100644 index 0000000..3418433 --- /dev/null +++ b/test_imports.py @@ -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.")