85 lines
3.0 KiB
Python
85 lines
3.0 KiB
Python
"""Configura ODBC portable desde config/odbc/."""
|
|
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from ..constants import IS_WINDOWS, ODBC_DIR
|
|
from ..utils.logger import app_logger
|
|
|
|
|
|
def _write_portable_odbc_ini(odbc_dir: Path) -> None:
|
|
"""Genera odbcinst.ini mínimo si no existe."""
|
|
inst = odbc_dir / "odbcinst.ini"
|
|
if inst.exists():
|
|
return
|
|
|
|
if IS_WINDOWS:
|
|
driver_path = odbc_dir / "msodbcsql18.dll"
|
|
if not driver_path.exists():
|
|
for candidate in odbc_dir.glob("msodbcsql*.dll"):
|
|
driver_path = candidate
|
|
break
|
|
driver_line = str(driver_path.resolve()) if driver_path.exists() else "msodbcsql18.dll"
|
|
content = f"""[ODBC Driver 18 for SQL Server]
|
|
Description=Microsoft ODBC Driver 18 for SQL Server
|
|
Driver={driver_line}
|
|
UsageCount=1
|
|
"""
|
|
else:
|
|
# Los .so embebidos viven en config/odbc/lib (no en la raíz). Buscar ahí
|
|
# primero y usar SIEMPRE la ruta absoluta del archivo versionado real
|
|
# (p. ej. libmsodbcsql-18.5.so.1.1); un nombre suelto como
|
|
# "libmsodbcsql-18.so" no resuelve porque ese symlink apunta a /opt.
|
|
lib_dir = odbc_dir / "lib"
|
|
search_dirs = [d for d in (lib_dir, odbc_dir) if d.is_dir()]
|
|
so_path = None
|
|
for base in search_dirs:
|
|
# Preferir el archivo real versionado sobre symlinks (que pueden estar rotos).
|
|
candidates = sorted(
|
|
(p for p in base.glob("libmsodbcsql-18*.so*") if p.is_file() and not p.is_symlink()),
|
|
key=lambda p: len(p.name),
|
|
reverse=True,
|
|
)
|
|
if not candidates:
|
|
candidates = [p for p in base.glob("libmsodbcsql-18*.so*") if p.exists()]
|
|
if candidates:
|
|
so_path = candidates[0]
|
|
break
|
|
driver_line = str(so_path.resolve()) if so_path else "libmsodbcsql-18.so"
|
|
content = f"""[ODBC Driver 18 for SQL Server]
|
|
Description=Microsoft ODBC Driver 18 for SQL Server
|
|
Driver={driver_line}
|
|
UsageCount=1
|
|
"""
|
|
inst.write_text(content, encoding="utf-8")
|
|
|
|
ini = odbc_dir / "odbc.ini"
|
|
if not ini.exists():
|
|
ini.write_text("[ODBC Data Sources]\n", encoding="utf-8")
|
|
|
|
|
|
def configure_odbc_environment() -> None:
|
|
"""Apunta pyodbc al driver embebido en config/odbc si está disponible."""
|
|
if not ODBC_DIR.is_dir():
|
|
return
|
|
|
|
lib_dir = ODBC_DIR / "lib"
|
|
if lib_dir.is_dir():
|
|
existing = os.environ.get("LD_LIBRARY_PATH", "")
|
|
lib_path = str(lib_dir.resolve())
|
|
if lib_path not in existing.split(":"):
|
|
os.environ["LD_LIBRARY_PATH"] = (
|
|
f"{lib_path}:{existing}" if existing else lib_path
|
|
)
|
|
|
|
_write_portable_odbc_ini(ODBC_DIR)
|
|
odbc_sys = str(ODBC_DIR.resolve())
|
|
os.environ["ODBCSYSINI"] = odbc_sys
|
|
os.environ["ODBCINI"] = str((ODBC_DIR / "odbc.ini").resolve())
|
|
|
|
if IS_WINDOWS:
|
|
os.environ["PATH"] = odbc_sys + os.pathsep + os.environ.get("PATH", "")
|
|
|
|
app_logger.debug(f"ODBC configurado: ODBCSYSINI={odbc_sys}")
|