Enhance database URL handling in Alembic environment
- Added a new helper function to strip unwanted characters from environment variable URLs, improving the normalization process. - Updated the `get_database_url` function to validate the database URL scheme and provide clearer error messages for misconfigurations. - Expanded the environment variable checks to include `DATABASE_URL`, enhancing flexibility for different deployment scenarios. These changes aim to improve the robustness and clarity of database connection handling in the application.
This commit is contained in:
@@ -3,7 +3,7 @@ import logging
|
||||
import os
|
||||
import sys
|
||||
from logging.config import fileConfig
|
||||
from urllib.parse import quote_plus
|
||||
from urllib.parse import quote_plus, urlparse
|
||||
|
||||
from alembic import context
|
||||
from alembic.operations import ops
|
||||
@@ -18,9 +18,15 @@ logger = logging.getLogger(__name__)
|
||||
config = context.config
|
||||
|
||||
|
||||
def _strip_env_url(raw: str) -> str:
|
||||
"""Quita espacios/comillas típicos de secretos CI (.env, Gitea)."""
|
||||
url = raw.strip().strip('"').strip("'")
|
||||
return url
|
||||
|
||||
|
||||
def _normalize_alembic_sqlalchemy_url(url: str) -> str:
|
||||
"""Alembic usa el driver síncrono psycopg2; normaliza DSN típicos de app/tests."""
|
||||
url = url.strip()
|
||||
url = _strip_env_url(url)
|
||||
if url.startswith("postgresql+asyncpg://"):
|
||||
return url.replace("postgresql+asyncpg://", "postgresql+psycopg2://", 1)
|
||||
if url.startswith("postgresql+psycopg2://"):
|
||||
@@ -34,11 +40,18 @@ def _normalize_alembic_sqlalchemy_url(url: str) -> str:
|
||||
|
||||
def get_database_url():
|
||||
"""Obtiene la URL de la base de datos (PostgreSQL) desde variables de entorno o alembic.ini."""
|
||||
# CI / pytest: misma URL que los tests (secret TEST_DATABASE_URL) o DATABASE_URL explícita
|
||||
# CI / pytest: misma URL que los tests (secret TEST_DATABASE_URL) o DATABASE_URL explícita.
|
||||
# Nota: ("X") sin coma es str, no tupla; el for iteraría caracteres y jamás leería la variable.
|
||||
for env_key in ("TEST_DATABASE_URL"):
|
||||
raw = os.environ.get(env_key)
|
||||
if raw and raw.strip():
|
||||
return _normalize_alembic_sqlalchemy_url(raw)
|
||||
normalized = _normalize_alembic_sqlalchemy_url(raw)
|
||||
if not urlparse(normalized).scheme:
|
||||
raise RuntimeError(
|
||||
f"{env_key} no es una URL válida (falta esquema). "
|
||||
"Ejemplo: postgresql://usuario:clave@host:5432/nombre_bd"
|
||||
)
|
||||
return normalized
|
||||
|
||||
# Construcción desde settings (CORE_DB_* en .env / entorno)
|
||||
host = settings.CORE_DB_HOST
|
||||
@@ -58,11 +71,11 @@ def get_database_url():
|
||||
|
||||
# Fallback al archivo de configuración
|
||||
url = config.get_main_option("sqlalchemy.url")
|
||||
if not url:
|
||||
if not url or "${" in url or "%(" in url:
|
||||
raise RuntimeError(
|
||||
"No se ha configurado la cadena de conexión a PostgreSQL. "
|
||||
"Define TEST_DATABASE_URL o DATABASE_URL, o CORE_DB_HOST/CORE_DB_USER/CORE_DB_PASSWORD/CORE_DB_NAME, "
|
||||
"o sqlalchemy.url en alembic.ini"
|
||||
"Define TEST_DATABASE_URL o DATABASE_URL, o variables CORE_DB_*; "
|
||||
"sqlalchemy.url en alembic.ini con placeholders ${...} no está soportado."
|
||||
)
|
||||
|
||||
return url
|
||||
|
||||
Reference in New Issue
Block a user