3
0
Fork 0

feat: add alembic config/utility functions, for migrations admin

wuttaweb will have some admin tools exposed soon hopefully
This commit is contained in:
Lance Edgar 2025-12-21 14:29:54 -06:00
parent 5a2748c775
commit 189a53c82a
3 changed files with 216 additions and 8 deletions

View file

@ -6,13 +6,18 @@ import tempfile
from unittest import TestCase
from wuttjamaican.conf import WuttaConfig
from wuttjamaican.testing import ConfigTestCase, DataTestCase
try:
import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.engine import Engine
from sqlalchemy.pool import NullPool
from alembic import command as alembic_command
from alembic.config import Config as AlembicConfig
from alembic.script import ScriptDirectory
from wuttjamaican.db import conf
from wuttjamaican.db import conf as mod
except ImportError:
pass
else:
@ -154,3 +159,111 @@ else:
}
)
self.assertTrue(engine.pool._pre_ping)
class TestMakeAlembicConfig(ConfigTestCase):
def test_defaults(self):
# without config file
self.assertFalse(self.config.files_read)
alembic = mod.make_alembic_config(self.config)
self.assertIsInstance(alembic, AlembicConfig)
self.assertIsNone(alembic.config_file_name)
self.assertIsNone(alembic.get_main_option("script_location"))
self.assertIsNone(alembic.get_main_option("version_locations"))
# with config file
path = self.write_file("test.ini", "[alembic]")
self.config.files_read = [path]
alembic = mod.make_alembic_config(self.config)
self.assertIsInstance(alembic, AlembicConfig)
self.assertEqual(alembic.config_file_name, path)
self.assertIsNone(alembic.get_main_option("script_location"))
self.assertIsNone(alembic.get_main_option("version_locations"))
def test_configured(self):
self.config.setdefault("alembic.script_location", "wuttjamaican.db:alembic")
self.config.setdefault(
"alembic.version_locations", "wuttjamaican.db:alembic/versions"
)
alembic = mod.make_alembic_config(self.config)
self.assertIsInstance(alembic, AlembicConfig)
self.assertEqual(
alembic.get_main_option("script_location"), "wuttjamaican.db:alembic"
)
self.assertEqual(
alembic.get_main_option("version_locations"),
"wuttjamaican.db:alembic/versions",
)
class TestGetAlembicScriptdir(ConfigTestCase):
def test_basic(self):
self.config.setdefault("alembic.script_location", "wuttjamaican.db:alembic")
self.config.setdefault(
"alembic.version_locations", "wuttjamaican.db:alembic/versions"
)
# can provide alembic config
alembic = mod.make_alembic_config(self.config)
script = mod.get_alembic_scriptdir(self.config, alembic)
self.assertIsInstance(script, ScriptDirectory)
# but also can omit it
script = mod.get_alembic_scriptdir(self.config)
self.assertIsInstance(script, ScriptDirectory)
class TestCheckAlembicCurrent(DataTestCase):
def make_config(self, **kwargs):
sqlite_path = self.write_file("test.sqlite", "")
self.sqlite_engine_url = f"sqlite:///{sqlite_path}"
config_path = self.write_file(
"test.ini",
f"""
[wutta.db]
default.url = {self.sqlite_engine_url}
[alembic]
script_location = wuttjamaican.db:alembic
version_locations = wuttjamaican.db:alembic/versions
""",
)
return super().make_config([config_path], **kwargs)
def test_basic(self):
alembic = mod.make_alembic_config(self.config)
self.assertIsNotNone(alembic.get_main_option("script_location"))
self.assertIsNotNone(alembic.get_main_option("version_locations"))
# false by default, since tests use MetaData.create_all()
# instead of migrations for setup
self.assertFalse(mod.check_alembic_current(self.config, alembic))
# and to further prove the point, alembic_version table is missing
self.assertEqual(
self.session.execute(sa.text("select count(*) from person")).scalar(),
0,
)
self.assertRaises(
sa.exc.OperationalError,
self.session.execute,
sa.text("select count(*) from alembic_version"),
)
# but we can 'stamp' the DB to declare its current revision
alembic_command.stamp(alembic, "heads")
# now the alembic_version table exists
self.assertEqual(
self.session.execute(
sa.text("select count(*) from alembic_version")
).scalar(),
1,
)
# and now Alembic knows we are current
self.assertTrue(mod.check_alembic_current(self.config, alembic))