Package: db-migrator
Settingsdbmigratorrequires a few settings to work:--migrations-directory: the directory that contains all the migrations--context: name of the python package containing an entry point to the
migrations directory--db-connection-string: database host, port, name, user, password etc
for connecting to postgres--config: a config file that contains the above settingsSeedbmigrator-h.To set the migrations directory using an entry point, in mymodulesetup.py:setup(
    ...
    entry_points={
        'dbmigrator': [
            'migrations_directory = mymodule.main:migrations_directory',
            ],
        },
    )Important note: For the settings fromsetup.pyto be picked up, before
runningdbmigrator, first runpython setup.py developorpython setup.py install.Then inmymodule/main.py:import os

migrations_directory = '{}/sql/migrations'.format(
    os.path.abspath(os.path.dirname(__file__)))or:import os

def migrations_directory():
    return '{}/sql/migrations'.format(
        os.path.abspath(os.path.dirname(__file__)))or with a config file,development.ini, that looks like this:[app:main]
db-connection-string = postgres://dbuser@localhost/dbnamegenerateGenerate a migration script in the migrations directory.Example usage:dbmigrator generate add_id_to_usersgenerates a file calledmigrations/20151217170514_add_id_to_users.pywith content:# Uncomment should_run if this is a repeat migration
# def should_run(cursor):
#     # TODO return True if migration should run


def up(cursor):
    # TODO migration code
    pass


def down(cursor):
    # TODO rollback code
    passinitInitialize schema migrations table.  By default, all the migrations are assumed
to have been applied to the database.Example usage:dbmigrator --db-connection-string='postgres://dbuser@localhost/dbname' initThere is an option to manually set the version of the database.  For example,
if none of the migrations have been applied to the database, you can:dbmigrator --config=development.ini init --version=0listList migration versions, names, whether it has been applied and the date
applied.Example usage:$ dbmigrator --config=development.ini list
version        | name            | is applied | date applied
----------------------------------------------------------------------
20151217170514   add_id_to_users   True         2016-01-31 00:15:01.692570+01:00
20151218145832   add_karen_to_us   False*
20160107200351   blah              deferredA*in the “is applied” column means that the migration is a repeated
migration.To see the full migration name, use--wide:$ dbmigrator --config=development.ini list --wide
version        | name               | is applied | date applied
----------------------------------------------------------------------
20151217170514   add_id_to_users      True         2016-01-31 00:15:01.692570+01:00
20151218145832   add_karen_to_users   False*
20160107200351   blah                 deferredmigrateRun pending migrations.For example, with two migrations in the migrations directory,migrations/20151217170514_add_id_to_users.py:from dbmigrator import super_user

def up(cursor):
    # TODO migration code
    pass

    # if a super user database connection is needed
    with super_user() as super_cursor:
        pass

def down(cursor):
    # TODO rollback code
    passandmigrations/20151218145832_add_karen_to_users.py:def up(cursor):
    cursor.execute('ALTER TABLE users ADD COLUMN karen TEXT')

def down(cursor):
    cursor.execute('ALTER TABLE users DROP COLUMN karen')To run the migrations:$ dbmigrator migrate
Running migration 20151217170514 add_id_to_users

Running migration 20151218145832 add_karen_to_users
---
+++
@@ -4005,21 +4005,22 @@
     first_name text,
     firstname text,
     last_name text,
     surname text,
     full_name text,
     fullname text,
     suffix text,
     title text,
     email text,
     website text,
-    is_moderated boolean
+    is_moderated boolean,
+    karen text
 );

 ALTER TABLE public.users OWNER TO rhaptos;

 --
 -- Name: abstractid; Type: DEFAULT; Schema: public; Owner: rhaptos
 --

 ALTER TABLE ONLY abstracts ALTER COLUMN abstractid SET DEFAULT nextval('abstracts_abstractid_seq'::regclass);or to run migrations up to a specific version:$ dbmigrator migrate version=20151217170514
Running migration 20151217170514 add_id_to_usersif all migrations have already been run:$ dbmigrator migrate
No pending migrations.  Database is up to date.To write a repeat migration, make sure your migration hasshould_rundefined:def should_run(cursor):
    return os.path.exists('data.txt')


def up(cursor):
    with open('data.txt') as f:
        data = f.read()
    cursor.execute('INSERT INTO table VALUES (%s)', (data,))


def down(cursor):
    passThe above migration will runevery timemigrateis called, except if it
is marked as “deferred”.upis run ifshould_runreturns True.To write a deferred migration, add@deferredto the up function:from dbmigrator import deferred


@deferred
def up(cursor):
    # this migration is automatically deferredThe above migration will not run unless you usemigrate--run-deferred.rollbackRollback a migration.For example, with two migrations in the migrations directory,migrations/20151217170514_add_id_to_users.py:def up(cursor):
    # TODO migration code
    pass

def down(cursor):
    # TODO rollback code
    passandmigrations/20151218145832_add_karen_to_users.py:def up(cursor):
    cursor.execute('ALTER TABLE users ADD COLUMN karen TEXT')

def down(cursor):
    cursor.execute('ALTER TABLE users DROP COLUMN karen')Make sure the database is up to date:$ dbmigrator migrate
No pending migrations.  Database is up to date.Now rollback the last migration:$ dbmigrator rollback
Rolling back migration 20151218145832 add_karen_to_users
---
+++
@@ -4005,22 +4005,21 @@
     first_name text,
     firstname text,
     last_name text,
     surname text,
     full_name text,
     fullname text,
     suffix text,
     title text,
     email text,
     website text,
-    is_moderated boolean,
-    karen text
+    is_moderated boolean
 );

 ALTER TABLE public.users OWNER TO rhaptos;

 --
 -- Name: abstractid; Type: DEFAULT; Schema: public; Owner: rhaptos
 --

 ALTER TABLE ONLY abstracts ALTER COLUMN abstractid SET DEFAULT nextval('abstracts_abstractid_seq'::regclass);To rollback the last 2 migrations:$ dbmigrator rollback --steps=2
Rolling back migration 20151218145832 add_karen_to_users
---
+++
@@ -4005,22 +4005,21 @@
     first_name text,
     firstname text,
     last_name text,
     surname text,
     full_name text,
     fullname text,
     suffix text,
     title text,
     email text,
     website text,
-    is_moderated boolean,
-    karen text
+    is_moderated boolean
 );

 ALTER TABLE public.users OWNER TO rhaptos;

 --
 -- Name: abstractid; Type: DEFAULT; Schema: public; Owner: rhaptos
 --

 ALTER TABLE ONLY abstracts ALTER COLUMN abstractid SET DEFAULT nextval('abstracts_abstractid_seq'::regclass);

Rolling back migration 20151217170514 add_id_to_usersmarkMark a migration as completed, not completed or deferred.Example usage:$ dbmigrator --config=development.ini --migrations-directory=migrations/ list
name                      | is applied | date applied
----------------------------------------------------------------------
20151217170514_add_id_to_   True         2016-01-31 00:15:01.692570+01:00
20151218145832_add_karen_   False
20160107200351_blah         FalseTo mark a migration as not completed:$ dbmigrator --config=development.ini --migrations-directory=migrations/ mark -f 20151217170514
Migration 20151217170514 marked as not been run

$ dbmigrator --config=development.ini --migrations-directory=migrations/ list
name                      | is applied | date applied
----------------------------------------------------------------------
20151217170514_add_id_to_   False
20151218145832_add_karen_   False
20160107200351_blah         FalseTo mark a migration as completed:$ dbmigrator --config=development.ini --migrations-directory=migrations/ mark -f 20151217170514
Migration 20151217170514 marked as completed

$ dbmigrator --config=development.ini --migrations-directory=migrations/ list
name                      | is applied | date applied
----------------------------------------------------------------------
20151217170514_add_id_to_   True         2016-06-13 16:39:58.777893+01:00
20151218145832_add_karen_   False
20160107200351_blah         FalseTo mark a migration as deferred means to ignore a migration when runningmigrateorrollback:$ dbmigrator --config=development.ini --migrations-directory=migrations/ mark -d 20151217170514
Migration 20151217170514 marked as deferred

$ dbmigrator --config=development.ini --migrations-directory=migrations/ list
name                      | is applied | date applied
----------------------------------------------------------------------
20151217170514_add_id_to_   deferred     None
20151218145832_add_karen_   False
20160107200351_blah         FalseCHANGELOG1.1.0 (2018-01-03)Add db-config-ini-key to CLI optionsAdd--sort(version or applied) todbmigrator listAllow mark to accept multiple timestampsSet dbmigrator settings before running utils testsAdd quiet switchAdd tests for no migrations to rollbackConvert most output to loggingExplicitly close all postgres db connections1.0.2 (2017-09-25)create a savepoint around should_run - rollback on false, to restore db stateAdd__version__to dbmigrator1.0.1 (2017-09-14)Update minimum version of psycopg2 required1.0.0 (2017-08-24)Add “*” to indicate repeated migrations inlistRaise SystemExit whenmarkmigration not foundAdd deferred migrationsAdd repeat conditional migrationsChange print statement to logger.debugReduce noise in tests when installing test packagesAdd CLI test for rollbackAdd CLI test for migrateAdd super user database connectionsMove logger from __init__.py to utils.pyChange python 3.4 to 3.5 in .travis.yml0.2.0 (2016-06-24)Add psycopg2 wait callback so ctrl-c stops a migrationImplement mark a migration as deferred:mark-dAdd –wide option forlistto display the full migration nameUpdate command usage in READMEAdd help message to dbmigrator commandsWarn user withdbmigrator init--helpif schema migrations doesn’t existAdd CLI test for generating migrations0.1.4 (2016-05-12)Changedbmigrator listto list version and migration name separately0.1.3 (2016-04-19)Separate cli tests into different test casesChange test config to use the travis databaseChange logger.warn to logger.warningAdd test case for cli verbose optionAdd tests fordbmigrator listAdd CLI init test case for multiple contextsAdd travis and coveralls badges to READMEMove cli.main import to base test caseRefactor code for marking a migration as completed or notAddmarkcommand for marking a migration as completed or notAdd tests for themarkcommandUpdate README with example usage for themarkcommand0.1.2 (2016-03-18)bug:Fixlistto not explode when no migrations directories are givenLog warning message forlistif schema_migrations table doesn’t existChange--verboseto set the logger level to debugAdd test for utils.timestampAdd test for utils.rollback_migrationAdd test for utils.run_migrationAdd test for utils.get_pending_migrationsAdd test for utils.get_migrationsAdd test for utils.import_migrationMakedbmigrator generategenerate pep8 compliant codeFixdbmigrator generatemigrations directory lookupAdd test for utils.with_cursorAdd test for utils.get_settings_from_configAdd integration tests with test packagesAdd pep8 to travisAdd a logger for dbmigrator that writes to stdoutChange version information option to-VSort migrations by their filename, not the full path0.1.1 (2016-02-24)Stop changing schema_migrations data if the table already existsRewrite--versionto use argparse version actionAdd unit test for--versionAdd travis CI configuration fileFix default context (working directory) being a string instead of a list0.1.0 (2016-02-12)Allow multiple migrations directories / context to be specifiedAdd –verbose which prints the configuration used by dbmigratorUse datetimeutcnowinstead ofnowfor timestampsAdd--versionto show the version of db-migrator installed0.0.7 (2016-02-10)Add option--contextto dbmigrator in order to load entry pointsRaise error if config file is specified but not found0.0.6 (2016-02-08)Fix missing migrations directory the “init” command0.0.5 (2016-02-08)Include CHANGELOG in distribution’s manifest0.0.4 (2016-02-08)Show warning message instead of error if migrations directory is undefinedAdd CHANGELOG0.0.3 (2016-02-08)Return error if migrations directory is undefined0.0.2 (2016-02-03)Fix invalid rst in READMEUpdate setup.py description and long_descriptionUpdate setup.py to include README as the description and fix urlUpdate README and cli after removing default value for config fileRemove default config path (development.ini)Add dbmigrator list commandFix dbmigrator rollback to stop if there are no migrations to rollbackPrint message after initializing schema migrationsAdd note to runpython setup.py installif using entry pointsAdd migrations directory setting from setup.py entry point in READMEUpdate command names for init and generate in READMEGet settings from setup.py entry pointsRemove __init__.py generation in migrations directoryAdd option version to dbmigrator init for setting the initial versionRename “generate_migration” command to “generate”Rename “init_schema_migrations” command to “init”Change the way migrations are imported so it works in python2Add “applied” timestamp to schema migrations tableAdd#-*-coding:utf-8-*-to the top of generated migration filesAdd READMEAdd command “rollback” to rollback migrationsAdd command “migrate” to run pending migrationsAdd migrations to table when running init_schema_migrationsAdd command for creating the schema migrations tableCreate dbmigrator cli and “generate_migration” commandCreate dbmigrator python package