Source code for timelink.migrations

# This is a file for the "migrations" folder in timelink.
# It is used to hold the alembic related files and configurations.
# These allow for the update of databases when the models from within
# the timelink package without user intervention.
#
# this file and the techniques used are based on the following SO answer:
# https://stackoverflow.com/questions/73633063/distribute-alembic-migration-scripts-in-application-package

from pathlib import Path

from alembic import command
from alembic.runtime import migration
from alembic.config import Config
from alembic.script import ScriptDirectory
from sqlalchemy import engine


ROOT_PATH = Path(__file__).parent.parent
ALEMBIC_CFG = Config(ROOT_PATH / "alembic.ini")
ALEMBIC_CFG.set_main_option("script_location", str(ROOT_PATH / "migrations"))

# Naming conventions for foreign keys
# https://alembic.sqlalchemy.org/en/latest/naming.html#naming-conventions
naming_convention = {
    "fk":
    "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
}


[docs] def set_db_url(db_url): """Set the database URL in the alembic configuration. This should be done before running any alembic commands in a specific database """ ALEMBIC_CFG.set_section_option("alembic", "sqlalchemy.url", db_url)
# Unused
[docs] def get_versions(base='base', head='heads'): """Get the list of versions of the database. Args: base (str): The base revision to start from. head (str): The head revision to stop at. """ script = ScriptDirectory.from_config(ALEMBIC_CFG) revisions = list(script.walk_revisions(base, head)) return revisions
[docs] def current(db_url, verbose=False): """Get the current revision of the database.""" set_db_url(db_url) command.current(ALEMBIC_CFG, verbose=verbose)
[docs] def upgrade(db_url, revision="heads"): """Upgrade the database to a given revision (default most recent).""" set_db_url(db_url) command.upgrade(ALEMBIC_CFG, revision)
[docs] def downgrade(db_url, revision): """Downgrade the database to the given revision.""" set_db_url(db_url) command.downgrade(ALEMBIC_CFG, revision)
[docs] def heads(db_url): """ Show heads of database""" set_db_url(db_url) engine_ = engine.create_engine(db_url) with engine_.begin() as connection: migration_context = migration.MigrationContext.configure(connection) heads = migration_context.get_current_heads() return heads
[docs] def stamp(db_url, revision: str): """ Stamp current revision to a given revision Use "heads" to mark the database as up-to-date """ set_db_url(db_url) command.stamp(ALEMBIC_CFG, revision)
[docs] def history(verbose=False): """Show the migration history.""" command.history(ALEMBIC_CFG, verbose=verbose)
[docs] def autogenerate(db_url, message): """Autogenerate migration script.""" set_db_url(db_url) command.revision(ALEMBIC_CFG, message=message, autogenerate=True)
[docs] def revision(db_url, message, autogenerate=False): """Create a new revision.""" set_db_url(db_url) command.revision(ALEMBIC_CFG, message=message, autogenerate=autogenerate)