11from __future__ import annotations
22
33import logging
4+ import re
45from pathlib import Path
56from typing import Any , Literal
67
78from sqlalchemy import create_engine , inspect , text
89
9- from memu .database .postgres .schema import get_metadata
10-
1110try : # Optional dependency for Postgres backend
1211 from alembic import command
1312 from alembic .config import Config as AlembicConfig
1817logger = logging .getLogger (__name__ )
1918
2019DDLMode = Literal ["create" , "validate" ]
20+ _UNESCAPED_CONFIGPARSER_PERCENT = re .compile (r"(?<!%)%(?!%)" )
21+
22+
23+ def _escape_for_config_parser (value : str ) -> str :
24+ return _UNESCAPED_CONFIGPARSER_PERCENT .sub ("%%" , value )
2125
2226
2327def make_alembic_config (* , dsn : str , scope_model : type [Any ]) -> AlembicConfig :
2428 cfg = AlembicConfig ()
2529 cfg .set_main_option ("script_location" , str (Path (__file__ ).with_name ("migrations" )))
26- cfg .set_main_option ("sqlalchemy.url" , dsn )
30+ cfg .set_main_option ("sqlalchemy.url" , _escape_for_config_parser ( dsn ) )
2731 cfg .attributes ["scope_model" ] = scope_model
2832 return cfg
2933
@@ -37,6 +41,8 @@ def run_migrations(*, dsn: str, scope_model: type[Any], ddl_mode: DDLMode = "cre
3741 scope_model: User scope model for scoped tables
3842 ddl_mode: "create" to create missing tables, "validate" to only check schema
3943 """
44+ from memu .database .postgres .schema import get_metadata
45+
4046 metadata = get_metadata (scope_model )
4147 engine = create_engine (dsn )
4248
0 commit comments