Skip to content

Commit 92c160a

Browse files
Use MB's much better approach via the internal Alembic API
1 parent bc258e8 commit 92c160a

File tree

1 file changed

+17
-50
lines changed

1 file changed

+17
-50
lines changed

cardinal_pythonlib/sqlalchemy/alembic_func.py

Lines changed: 17 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,20 @@
2626
2727
"""
2828

29-
from configparser import ConfigParser
3029
import logging
3130
import os
3231
import re
33-
import subprocess
34-
from tempfile import NamedTemporaryFile
3532
from typing import Tuple
3633

37-
from alembic.config import Config as AlembicConfig
38-
from alembic.util.exc import CommandError
34+
from alembic.command import revision as mk_revision
35+
from alembic.config import CommandLine, Config as AlembicConfig
3936
from alembic.runtime.migration import MigrationContext
4037
from alembic.runtime.environment import EnvironmentContext
4138
from alembic.script import ScriptDirectory
39+
from alembic.util.exc import CommandError
4240
from sqlalchemy.engine import create_engine
4341

4442
from cardinal_pythonlib.fileops import preserve_cwd
45-
from cardinal_pythonlib.sqlalchemy.session import get_safe_url_from_url
4643

4744
log = logging.getLogger(__name__)
4845

@@ -377,55 +374,25 @@ def create_database_migration_numbered_style(
377374
new_seq_str = str(new_seq_no).zfill(n_sequence_chars)
378375

379376
log.info(
380-
f"""
381-
Generating new revision with Alembic...
382-
Last revision was: {current_seq_str}
383-
New revision will be: {new_seq_str}
384-
[If it fails with "Can't locate revision identified by...", you might need
385-
to DROP the Alembic version table (by default named 'alembic_version', but
386-
you may have elected to change that in your env.py).]
387-
"""
377+
f"Generating new revision with Alembic. "
378+
f"Last revision was: {current_seq_str}. "
379+
f"New revision will be: {new_seq_str}. "
380+
f"(If the process fails with \"Can't locate revision identified "
381+
f'by...", you might need to DROP the Alembic version table; by '
382+
f"default that is named {DEFAULT_ALEMBIC_VERSION_TABLE!r}, but you "
383+
f"may have elected to change that in your 'env.py' file.)"
388384
)
389385

390386
alembic_ini_dir = os.path.dirname(alembic_ini_file)
387+
os.chdir(alembic_ini_dir)
391388

392-
def _call_alembic(_alembic_ini_filename):
393-
os.chdir(alembic_ini_dir)
394-
cmdargs = [
395-
"alembic",
396-
"-c",
397-
_alembic_ini_filename,
398-
"revision",
399-
"--autogenerate",
400-
"-m",
401-
message,
402-
"--rev-id",
403-
new_seq_str,
404-
]
405-
log.info(f"From directory {alembic_ini_dir!r}, calling: {cmdargs!r}")
406-
subprocess.call(cmdargs)
407-
389+
# https://github.com/sqlalchemy/alembic/discussions/1089
390+
namespace = CommandLine().parser.parse_args(["revision", "--autogenerate"])
391+
config = AlembicConfig(alembic_ini_file, cmd_opts=namespace)
408392
if db_url:
409-
# Override the database URL. This is a bit ugly, because it's not
410-
# obvious how to pass a URL directly to the "alembic revision" command.
411-
# I don't think there's an API for that, and "alembic revision --help"
412-
# doesn't show any URL options. So, a temporary config:
413-
safe_url = get_safe_url_from_url(db_url)
414-
alembic_cfg = AlembicConfig(alembic_ini_file)
415-
alembic_cfg.set_main_option("sqlalchemy.url", db_url)
416-
with NamedTemporaryFile(
417-
mode="w+t", dir=alembic_ini_dir, suffix=".ini"
418-
) as tmpfile:
419-
log.info(
420-
f"Overriding database URL with {safe_url}, "
421-
f"via temporary file {tmpfile.name}"
422-
)
423-
cfgparser: ConfigParser = alembic_cfg.file_config
424-
cfgparser.write(tmpfile)
425-
tmpfile.flush()
426-
_call_alembic(tmpfile.name)
427-
else:
428-
_call_alembic(alembic_ini_file)
393+
config.set_main_option("sqlalchemy.url", db_url)
394+
395+
mk_revision(config, message=message, autogenerate=True, rev_id=new_seq_str)
429396

430397

431398
def stamp_allowing_unusual_version_table(

0 commit comments

Comments
 (0)