Пример #1
0
 def test_nonpy_and_nonnumber_are_ignored(self):
   db = MigrationDb()
   db.populate_migrations_from_ls(["1_foo.py", "1_bar.pyc", "4-ohhi.py", "-9_kitty.py", "1_bar.html", ".", ".boo", "..", "123.py.gz", "hello_45.py", "__init__.py", "___init__.pyc", "hello.py", "hello.pyc"])
   self.assert_equal([
        "1_foo",
     ], db.list()
   )
Пример #2
0
 def test_migrations_can_be_initialized_from_directory(self):
   db = MigrationDb(directory=self.mock_migrations_dir)
   db.warn = WarningsMocker()
   
   self.assert_equal([
       "001_foo",
       "002_bar",
       "005_DEV_hello",
       "009_one",
       "09_two",
     ], db.list()
   )
Пример #3
0
 def test_dup_warnings(self):
   db = MigrationDb()
   db.warn = WarningsMocker()
   db.populate_migrations_from_ls([
     "17_foo.py",
     "017_bar.py",
     "0018_foo.py",
     "00018_foo.py",
     "180_hello.py",
   ])
   self.assert_equal(
     [
     u'There are multiple migrations with the same number 17: 017_bar, 17_foo',
     u'There are multiple migrations with the same number 18: 00018_foo, 0018_foo'
     ],
     db.warn.warnings
   )
Пример #4
0
  def test_load_migration_object(self):
    db = MigrationDb(directory=self.mock_migrations_dir)
    db.warn = WarningsMocker()

    for name in ['001_foo', '0001', '001', '01', '1', 1]:
      self.assert_attrs(db.load_migration_object(name),
        name = '001_foo',
        dev = False,
        sql_up = "INSERT INTO mock VALUES (1)",
      )

    for name in ['002_bar', '0002', '002', '02', '2', 2]:
      self.assert_attrs(db.load_migration_object(name),
        name = '002_bar',
        dev = False,
        sql_up = "INSERT INTO mock VALUES (2)",
      )

    for name in ['005_DEV_hello', '0005', '005', '05', '5', 5]:
      self.assert_attrs(db.load_migration_object(name),
        name = '005_DEV_hello',
        dev = True,
        sql_up = "INSERT INTO mock VALUES (5)",
      )

    for name in ['3', '02_foo', '2_foo', 3]:
      self.assert_raises(NoSuchMigrationError, lambda: db.load_migration_object(name))
Пример #5
0
 def test_migrations_sorted_by_numbers_not_ascii(self):
   db = MigrationDb(migrations=[
     "04_blah",
     "03_blah",
     "002_bar",
     "12_blah",
     "01_foo",
     "011_blah",
   ])
   self.assert_equal([
       "01_foo",
       "002_bar",
       "03_blah",
       "04_blah",
       "011_blah",
       "12_blah",
     ], db.list()
   )
Пример #6
0
  def test_all_migrations_applied(self):
    db = MigrationDb(migrations = ['001_foo', '002_DEV_bar', '005_omg', '006_DEV_hello'])
    si = MigrationState(migration_db=db)
    si.init()

    si.mark_as_applied('005_omg')
    si.mark_as_applied('001_foo')
    si.mark_as_applied('009_bogus')

    self.assert_equal(['001_foo', '005_omg', '009_bogus'], si.all_migrations_applied())
Пример #7
0
  def test_is_dev_migration(self):
    db = MigrationDb()
    self.assert_equal(False, db.is_dev_migration("1_foo"))
    self.assert_equal(False, db.is_dev_migration("1DEV_foo"))
    self.assert_equal(False, db.is_dev_migration("1_DEVELOPER_foo"))

    self.assert_equal(True, db.is_dev_migration("1_DEV_foo"))
    self.assert_equal(True, db.is_dev_migration("005_DEV_bar"))
    self.assert_equal(True, db.is_dev_migration("1__DEV__foo"))
Пример #8
0
 def test_dups_and_missing_numbers_ok(self):
   db = MigrationDb(migrations = [
     "9_sweet",
     "8_blah_one",
     "7_blah",
     "10_gah",
     "8_blah_three",
     "1_foo",
     "8_blah_two",
   ])
   self.assert_equal([
       "1_foo",
       "7_blah",
       "8_blah_one",
       "8_blah_three",
       "8_blah_two",
       "9_sweet",
       "10_gah",
     ], db.list()
   )
Пример #9
0
    def test_when_doing_something_then_loggged(self):
        db = MigrationDb(directory=self.mock_migrations_dir)
        db.warn = WarningsMocker()
        si = MigrationState(migration_db=db, dev=True)
        si.init()

        si.apply('001_foo')
        si.mark_as_unapplied('001_foo')
        si.apply('001_foo')
        si.mark_as_applied('005_omg')
        si.unapply('001_foo')

        self.assert_equal([
            ("apply", "001_foo", "success"),
            ("mark_as_unapplied", "001_foo", "success"),
            ("apply", "001_foo", "success"),
            ("mark_as_applied", "005_omg", "success"),
            ("unapply", "001_foo", "success"),
        ], [row[:3] for row in get_log()])
        self.assert_equal(True, isinstance(get_log()[0][3], datetime))
Пример #10
0
  def test_find_unique_migration_by_number(self):
    db = MigrationDb(directory=self.mock_migrations_dir)
    db.warn = WarningsMocker()

    self.assert_equal("001_foo", db.find_unique_migration_by_number(1))
    self.assert_equal("002_bar", db.find_unique_migration_by_number(2))
    self.assert_equal(None, db.find_unique_migration_by_number(3))
    self.assert_raises(AmbiguousMigrationNameError, lambda: db.find_unique_migration_by_number(9))
Пример #11
0
    def test_when_doing_something_then_loggged(self):
        db = MigrationDb(directory=self.mock_migrations_dir)
        db.warn = WarningsMocker()
        si = MigrationState(migration_db=db, dev=True)
        si.init()

        si.apply("001_foo")
        si.mark_as_unapplied("001_foo")
        si.apply("001_foo")
        si.mark_as_applied("005_omg")
        si.unapply("001_foo")

        self.assert_equal(
            [
                ("apply", "001_foo", "success"),
                ("mark_as_unapplied", "001_foo", "success"),
                ("apply", "001_foo", "success"),
                ("mark_as_applied", "005_omg", "success"),
                ("unapply", "001_foo", "success"),
            ],
            [row[:3] for row in get_log()],
        )
        self.assert_equal(True, isinstance(get_log()[0][3], datetime))
Пример #12
0
  def test_load_migration_object_with_dups(self):
    db = MigrationDb(directory=self.mock_migrations_dir)
    db.warn = WarningsMocker()

    self.assert_attrs(db.load_migration_object('009_one'),
      name = '009_one',
      dev = False,
      sql_up = "INSERT INTO mock VALUES (9, 1)",
    )

    self.assert_attrs(db.load_migration_object('09_two'),
      name = '09_two',
      dev = False,
      sql_up = "INSERT INTO mock VALUES (9, 2)",
    )

    for name in ['0009', '009', '09', '9', 9]:
      self.assert_raises(AmbiguousMigrationNameError, lambda: db.load_migration_object(name))
Пример #13
0
  def test_plan_with_dev(self):
    # NOTE: si.mark_as_applied modifies global state, not si (MigrationState) object.
    #       There is only one meaningful MigrationState object per database,
    #       so it's an almost-singleton unless we support multiple databases at the same time.
    #       This makes testing quite ugly.
    db = MigrationDb(migrations = ['001_foo', '002_DEV_bar', '005_omg', '006_DEV_hello'])

    si = MigrationState(migration_db=db)
    si.init()
    self.assert_plans(si,
      ['up'],        [('001_foo', 'up')],
      ['upto', '5'], [('001_foo', 'up'), ('005_omg', 'up')],
      ['upto', '6'], [('001_foo', 'up'), ('005_omg', 'up')],
      ['all'],       [('001_foo', 'up'), ('005_omg', 'up')],
    )

    si = MigrationState(migration_db=db, dev=True)
    si.init()
    self.assert_plans(si,
      ['up'],        [('001_foo', 'up')],
      ['upto', '5'], [('001_foo', 'up'), ('002_DEV_bar', 'up'), ('005_omg', 'up')],
      ['upto', '6'], [('001_foo', 'up'), ('002_DEV_bar', 'up'), ('005_omg', 'up'), ('006_DEV_hello', 'up')],
      ['all'],       [('001_foo', 'up'), ('002_DEV_bar', 'up'), ('005_omg', 'up'), ('006_DEV_hello', 'up')],
    )

    si.mark_as_applied('001_foo')

    si = MigrationState(migration_db=db)
    si.init()
    self.assert_plans(si,
      ['up'],        [('005_omg', 'up')],
      ['upto', '5'], [('005_omg', 'up')],
      ['upto', '6'], [('005_omg', 'up')],
      ['all'],       [('005_omg', 'up')],
    )

    si = MigrationState(migration_db=db, dev=True)
    si.init()
    self.assert_plans(si,
      ['up'],        [('002_DEV_bar', 'up')],
      ['upto', '5'], [('002_DEV_bar', 'up'), ('005_omg', 'up')],
      ['upto', '6'], [('002_DEV_bar', 'up'), ('005_omg', 'up'), ('006_DEV_hello', 'up')],
      ['all'],       [('002_DEV_bar', 'up'), ('005_omg', 'up'), ('006_DEV_hello', 'up')],
    )

    si.mark_as_applied('002_DEV_bar')

    si = MigrationState(migration_db=db)
    si.init()
    self.assert_plans(si,
      ['up'],        [('005_omg', 'up')],
      ['upto', '5'], [('005_omg', 'up')],
      ['upto', '6'], [('005_omg', 'up')],
      ['all'],       [('005_omg', 'up')],
      ['down'],      [('001_foo', 'down')], # Is it better to always assume --dev on down ?
    )

    si = MigrationState(migration_db=db, dev=True)
    si.init()
    self.assert_plans(si,
      ['up'],        [('005_omg', 'up')],
      ['upto', '5'], [('005_omg', 'up')],
      ['upto', '6'], [('005_omg', 'up'), ('006_DEV_hello', 'up')],
      ['all'],       [('005_omg', 'up'), ('006_DEV_hello', 'up')],
      ['down'],      [('002_DEV_bar', 'down')],
    )
Пример #14
0
  def test_plan(self):
    db = MigrationDb(migrations = ['001_foo', '002_bar', '005_omg', '005_hello'])
    si = MigrationState(migration_db=db)

    si.init()
    
    self.assert_plans(si,
      ['apply', '1'],         [('001_foo', 'up')],
      ['apply', '001_foo'],   [('001_foo', 'up')],
      ['apply', '1', '2'],    [('001_foo', 'up'), ('002_bar', 'up')],
      ['unapply', '001_foo'], [],
      ['unapply', '1', '2'],  [],

      ['all'],                [('001_foo', 'up'), ('002_bar', 'up'), ('005_hello', 'up'), ('005_omg', 'up')],
      ['up'],                 [('001_foo', 'up')],
      ['down'],               [],

      ['to', '1'],            [('001_foo', 'up')],
      ['to', '2'],            [('001_foo', 'up'), ('002_bar', 'up')],
      ['upto', '2'],          [('001_foo', 'up'), ('002_bar', 'up')],
      ['upto', '002_bar'],    [('001_foo', 'up'), ('002_bar', 'up')],
      ['upto', '4'],          [('001_foo', 'up'), ('002_bar', 'up')],
      ['upto', '004_foo'],    NoSuchMigrationError,
      ['upto', '5'],          AmbiguousMigrationNameError,
      ['upto', '005_hello'],  [('001_foo', 'up'), ('002_bar', 'up'), ('005_hello', 'up')],
      ['upto', '005_omg'],    [('001_foo', 'up'), ('002_bar', 'up'), ('005_hello', 'up'), ('005_omg', 'up')],
      ['downto', '1'],        [],
      ['downto', '2'],        [],
    )
    
    si.mark_as_applied('002_bar')

    self.assert_plans(si,
      ['apply', '1'],         [('001_foo', 'up')],
      ['apply', '001_foo'],   [('001_foo', 'up')],
      ['apply', '1', '2'],    [('001_foo', 'up')],
      ['unapply', '001_foo'], [],
      ['unapply', '1', '2'],  [('002_bar', 'down')],

      ['all'],                [('001_foo', 'up'), ('005_hello', 'up'), ('005_omg', 'up')],
      ['up'],                 [('001_foo', 'up')],
      ['down'],               [('002_bar', 'down')],

      ['to', '1'],            [('002_bar', 'down'), ('001_foo', 'up')],
      ['to', '2'],            [('001_foo', 'up')],
      ['upto', '2'],          [('001_foo', 'up')],
      ['upto', '002_bar'],    [('001_foo', 'up')],
      ['upto', '4'],          [('001_foo', 'up')],
      ['upto', '004_foo'],    NoSuchMigrationError,
      ['upto', '5'],          AmbiguousMigrationNameError,
      ['upto', '005_hello'],  [('001_foo', 'up'), ('005_hello', 'up')],
      ['upto', '005_omg'],    [('001_foo', 'up'), ('005_hello', 'up'), ('005_omg', 'up')],
      ['downto', '1'],        [('002_bar', 'down')],
      ['downto', '2'],        [],
    )

    si.mark_as_applied('001_foo')

    self.assert_plans(si,
      ['apply', '1'],         [],
      ['apply', '001_foo'],   [],
      ['apply', '1', '2'],    [],
      ['unapply', '001_foo'], [('001_foo', 'down')],
      ['unapply', '1', '2'],  [('001_foo', 'down'), ('002_bar', 'down')],

      ['all'],                [('005_hello', 'up'), ('005_omg', 'up')],
      ['up'],                 [('005_hello', 'up')],
      ['down'],               [('002_bar', 'down')],

      ['to', '1'],            [('002_bar', 'down')],
      ['to', '2'],            [],
      ['upto', '2'],          [],
      ['upto', '002_bar'],    [],
      ['upto', '4'],          [],
      ['upto', '004_foo'],    NoSuchMigrationError,
      ['upto', '5'],          AmbiguousMigrationNameError,
      ['upto', '005_hello'],  [('005_hello', 'up')],
      ['upto', '005_omg'],    [('005_hello', 'up'), ('005_omg', 'up')],
      ['downto', '1'],        [('002_bar', 'down')],
      ['downto', '2'],        [],
    )

    si.mark_as_unapplied('002_bar')

    self.assert_plans(si,
      ['apply', '1'],         [],
      ['apply', '001_foo'],   [],
      ['apply', '1', '2'],    [('002_bar', 'up')],
      ['unapply', '001_foo'], [('001_foo', 'down')],
      ['unapply', '1', '2'],  [('001_foo', 'down')],

      ['all'],                [('002_bar', 'up'), ('005_hello', 'up'), ('005_omg', 'up')],
      ['up'],                 [('002_bar', 'up')],
      ['down'],               [('001_foo', 'down')],

      ['to', '1'],            [],
      ['to', '2'],            [('002_bar', 'up')],
      ['upto', '2'],          [('002_bar', 'up')],
      ['upto', '002_bar'],    [('002_bar', 'up')],
      ['upto', '4'],          [('002_bar', 'up')],
      ['upto', '004_foo'],    NoSuchMigrationError,
      ['upto', '5'],          AmbiguousMigrationNameError,
      ['upto', '005_hello'],  [('002_bar', 'up'), ('005_hello', 'up')],
      ['upto', '005_omg'],    [('002_bar', 'up'), ('005_hello', 'up'), ('005_omg', 'up')],
      ['downto', '1'],        [],
      ['downto', '2'],        [],
    )

    si.mark_as_applied('002_bar')
    si.mark_as_applied('005_hello')
    si.mark_as_applied('005_omg')
    
    self.assert_plans(si,
      ['apply', '1'],         [],
      ['apply', '001_foo'],   [],
      ['apply', '1', '2'],    [],
      ['unapply', '001_foo'], [('001_foo', 'down')],
      ['unapply', '1', '2'],  [('001_foo', 'down'), ('002_bar', 'down')],

      ['all'],                [],
      ['up'],                 [],
      ['down'],               [('005_omg', 'down')],

      ['to', '1'],            [('005_omg', 'down'), ('005_hello', 'down'), ('002_bar', 'down')],
      ['to', '2'],            [('005_omg', 'down'), ('005_hello', 'down')],
      ['upto', '2'],          [],
      ['upto', '002_bar'],    [],
      ['upto', '4'],          [],
      ['upto', '004_foo'],    NoSuchMigrationError,
      ['upto', '5'],          AmbiguousMigrationNameError,
      ['upto', '005_hello'],  [],
      ['upto', '005_omg'],    [],
      ['downto', '1'],        [('005_omg', 'down'), ('005_hello', 'down'), ('002_bar', 'down')],
      ['downto', '2'],        [('005_omg', 'down'), ('005_hello', 'down')],
    )
Пример #15
0
 def handle(self, *args, **options):
     try:
         migrations_dir = settings.DMIGRATIONS_DIR
     except AttributeError:
         print "You need to add DMIGRATIONS_DIR to your settings"
         return
     migration_db = MigrationDb(directory = migrations_dir)
     migration_state = MigrationState(
         migration_db = migration_db, dev = options.get('dev')
     )
     verbosity = int(options.get('verbosity', 1))
     
     if not args or args[0] == 'help':
         self.print_help(sys.argv[0], 'dmigrate')
         return
     
     elif args[0] in 'all all_hard up down upto downto to apply unapply'.split():
         migration_state.init()
         for (migration_name, action) in migration_state.plan(*args):
             migration = migration_db.load_migration_object(migration_name)
             start_time = time.time()
             if action == 'up':
                 if verbosity >= 1:
                     print "Applying migration %s" % migration.name
                 if not options.get('print_plan'):
                     migration_state.apply(migration_name)
             else:
                 if verbosity >= 1:
                     print "Unapplying migration %s" % migration.name
                 if not options.get('print_plan'):
                     migration_state.unapply(migration_name)
             if options.get('print_time'):
                 print "Migration %s ran %.1f seconds" % (migration.name, time.time() - start_time)
     
     elif args[0] == 'mark_as_applied':
         migration_state.init()
         for name in args[1:]:
             resolved_name = migration_state.resolve_name(name)
             if resolved_name == None:
                 raise NoSuchMigrationError(name)
             migration_state.mark_as_applied(resolved_name)
     
     elif args[0] == 'mark_as_unapplied':
         migration_state.init()
         for name in args[1:]:
             resolved_name = migration_state.resolve_name(name)
             if resolved_name == None:
                 raise NoSuchMigrationError(name)
             migration_state.mark_as_unapplied(resolved_name)
     
     elif args[0] == 'list':
         migration_state.init()
         for migration_name in migration_db.list():
             if migration_state.is_applied(migration_name, use_cache=True):
                print "* [+] %s" % migration_name
             else:
                print "* [ ] %s" % migration_name
         migrations_not_in_db = migration_state.applied_but_not_in_db()
         if migrations_not_in_db:
             print "These migrations are marked as applied but cannot " \
                 "be found:"
             for migration_name in migrations_not_in_db:
                 print "* [?] %s" % migration_name
         return
     
     elif args[0] == 'init':
         migration_state.init()
     
     elif args[0] == 'cat':
         for name in args[1:]:
             print open(
                 migration_db.resolve_migration_path(name), 'r'
             ).read()
         return
     
     else:
         raise CommandError(
             'Argument should be one of: list, help, up, down, all, all_hard, init, '
             'apply, unapply, to, downto, upto, mark_as_applied, '
             'mark_as_unapplied'
         )
     
     # Ensure Django permissions and content_types have been created
     # NOTE: Don't run if django_content_type doesn't exist yet.
     if table_present('django_content_type'):
         from django.contrib.auth.management import create_permissions
         from django.db import models
         for app in models.get_apps():
             if verbosity >= 1:
                 create_permissions(app, set(), 2)
             else:
                 create_permissions(app, set(), 1)
Пример #16
0
    def handle(self, *args, **options):
        try:
            migrations_dir = settings.DMIGRATIONS_DIR
        except AttributeError:
            print "You need to add DMIGRATIONS_DIR to your settings"
            return
        migration_db = MigrationDb(directory = migrations_dir)
        migration_state = MigrationState(
            migration_db = migration_db, dev = options.get('dev')
        )
        verbosity = int(options.get('verbosity', 1))

        if not args or args[0] == 'help':
            # TODO: Do this without calling os.system
            os.system('python manage.py help dmigrate')
            return

        elif args[0] in 'all up down upto downto to apply unapply'.split():
            migration_state.init()
            for (migration_name, action) in migration_state.plan(*args):
                migration = migration_db.load_migration_object(migration_name)
                if action == 'up':
                    if verbosity >= 1:
                        print "Applying migration %s" % migration.name
                    if not options.get('print_plan'):
                        migration_state.apply(migration_name)
                else:
                    if verbosity >= 1:
                        print "Unapplying migration %s" % migration.name
                    if not options.get('print_plan'):
                        migration_state.unapply(migration_name)

        elif args[0] == 'mark_as_applied':
            migration_state.init()
            for name in args[1:]:
                resolved_name = migration_state.resolve_name(name)
                if resolved_name == None:
                    raise NoSuchMigrationError(name)
                migration_state.mark_as_applied(resolved_name)

        elif args[0] == 'mark_as_unapplied':
            migration_state.init()
            for name in args[1:]:
                resolved_name = migration_state.resolve_name(name)
                if resolved_name == None:
                    raise NoSuchMigrationError(name)
                migration_state.mark_as_unapplied(resolved_name)

        elif args[0] == 'list':
            migration_state.init()
            for migration_name in migration_db.list():
                if migration_state.is_applied(migration_name):
                   print "* [+] %s" % migration_name
                else:
                   print "* [ ] %s" % migration_name
            migrations_not_in_db = migration_state.applied_but_not_in_db()
            if migrations_not_in_db:
                print "These migrations are marked as applied but cannot " \
                    "be found:"
                for migration_name in migrations_not_in_db:
                    print "* [?] %s" % migration_name
            return

        elif args[0] == 'init':
            migration_state.init()

        elif args[0] == 'cat':
            for name in args[1:]:
                print open(
                    migration_db.resolve_migration_path(name), 'r'
                ).read()
            return

        else:
            raise CommandError(
                'Argument should be one of: list, help, up, down, all, init, '
                'apply, unapply, to, downto, upto, mark_as_applied, '
                'mark_as_unapplied'
            )

        # Ensure Django permissions and content_types have been created
        # NOTE: Don't run if django_content_type doesn't exist yet.
        if table_present('django_content_type'):
            from django.contrib.auth.management import create_permissions
            from django.db import models
            for app in models.get_apps():
                if verbosity >= 1:
                    create_permissions(app, set(), 2)
                else:
                    create_permissions(app, set(), 1)
Пример #17
0
 def test_migration_path(self):
   db = MigrationDb(directory=self.mock_migrations_dir)
   db.warn = WarningsMocker()
   
   self.assert_equal(self.mock_migrations_dir + '/010_foo.py', db.migration_path('foo'))