Beispiel #1
0
    def test_bool(self):
        """Testing MigrationList.__bool__"""
        migration_list = MigrationList()
        self.assertFalse(migration_list)

        migration_list.add_migration_info(app_label='tests',
                                          name='0001_initial')
        self.assertTrue(migration_list)
Beispiel #2
0
    def test_add_recorded_migration(self):
        """Testing MigrationList.add_recorded_migration"""
        recorded_migration1 = MigrationRecorder.Migration(
            app='tests',
            name='0001_initial',
            applied=True)
        recorded_migration2 = MigrationRecorder.Migration(
            app='tests',
            name='0002_add_field',
            applied=True)

        migration_list = MigrationList()
        migration_list.add_recorded_migration(recorded_migration1)
        migration_list.add_recorded_migration(recorded_migration2)

        self.assertEqual(
            migration_list._by_id,
            {
                ('tests', '0001_initial'): {
                    'app_label': 'tests',
                    'name': '0001_initial',
                    'migration': None,
                    'recorded_migration': recorded_migration1,
                },
                ('tests', '0002_add_field'): {
                    'app_label': 'tests',
                    'name': '0002_add_field',
                    'migration': None,
                    'recorded_migration': recorded_migration2,
                },
            })
        self.assertEqual(
            migration_list._by_app_label,
            {
                'tests': [
                    {
                        'app_label': 'tests',
                        'name': '0001_initial',
                        'migration': None,
                        'recorded_migration': recorded_migration1,
                    },
                    {
                        'app_label': 'tests',
                        'name': '0002_add_field',
                        'migration': None,
                        'recorded_migration': recorded_migration2,
                    },
                ],
            })
Beispiel #3
0
    def test_get_app_labels(self):
        """Testing MigrationList.get_app_labels"""
        migration_list = MigrationList()
        migration_list.add_migration_info(app_label='foo',
                                          name='0002_bar')
        migration_list.add_migration_info(app_label='tests',
                                          name='0001_initial')
        migration_list.add_migration_info(app_label='baz',
                                          name='0002_stuff')

        self.assertEqual(migration_list.get_app_labels(),
                         ['baz', 'foo', 'tests'])
Beispiel #4
0
 def test_from_names(self):
     """Testing MigrationList.from_names"""
     migration_list = MigrationList.from_names(
         app_label='tests',
         migration_names=['0001_initial', '0002_stuff'])
     self.assertTrue(migration_list.has_migration_info(app_label='tests',
                                                       name='0001_initial'))
     self.assertTrue(migration_list.has_migration_info(app_label='tests',
                                                       name='0002_stuff'))
Beispiel #5
0
    def test_add_migration(self):
        """Testing MigrationList.add_migration"""
        migration1 = InitialMigration('0001_initial', 'tests')
        migration2 = AddFieldMigration('0002_add_field', 'tests')

        migration_list = MigrationList()
        migration_list.add_migration(migration1)
        migration_list.add_migration(migration2)

        self.assertEqual(
            migration_list._by_id,
            {
                ('tests', '0001_initial'): {
                    'app_label': 'tests',
                    'name': '0001_initial',
                    'migration': migration1,
                    'recorded_migration': None,
                },
                ('tests', '0002_add_field'): {
                    'app_label': 'tests',
                    'name': '0002_add_field',
                    'migration': migration2,
                    'recorded_migration': None,
                },
            })
        self.assertEqual(
            migration_list._by_app_label,
            {
                'tests': [
                    {
                        'app_label': 'tests',
                        'name': '0001_initial',
                        'migration': migration1,
                        'recorded_migration': None,
                    },
                    {
                        'app_label': 'tests',
                        'name': '0002_add_field',
                        'migration': migration2,
                        'recorded_migration': None,
                    },
                ],
            })
Beispiel #6
0
    def test_add_migration_targets(self):
        """Testing MigrationList.add_migration_targets"""
        migration_list = MigrationList()
        migration_list.add_migration_targets([
            ('tests', '0001_initial'),
            ('tests', '0002_stuff'),
        ])

        self.assertEqual(
            migration_list._by_id,
            {
                ('tests', '0001_initial'): {
                    'app_label': 'tests',
                    'name': '0001_initial',
                    'migration': None,
                    'recorded_migration': None,
                },
                ('tests', '0002_stuff'): {
                    'app_label': 'tests',
                    'name': '0002_stuff',
                    'migration': None,
                    'recorded_migration': None,
                },
            })
        self.assertEqual(
            migration_list._by_app_label,
            {
                'tests': [
                    {
                        'app_label': 'tests',
                        'name': '0001_initial',
                        'migration': None,
                        'recorded_migration': None,
                    },
                    {
                        'app_label': 'tests',
                        'name': '0002_stuff',
                        'migration': None,
                        'recorded_migration': None,
                    },
                ],
            })
Beispiel #7
0
    def test_from_app_sig(self):
        """Testing MigrationList.from_app_sig"""
        app_sig = AppSignature(
            app_id='tests',
            applied_migrations=['0001_initial', '0002_stuff'])

        migration_list = MigrationList.from_app_sig(app_sig)
        self.assertTrue(migration_list.has_migration_info(app_label='tests',
                                                          name='0001_initial'))
        self.assertTrue(migration_list.has_migration_info(app_label='tests',
                                                          name='0002_stuff'))
Beispiel #8
0
    def test_run_checks_with_bad_history(self):
        """Testing MigrationExecutor.run_checks with bad history"""
        connection = connections[DEFAULT_DB_ALIAS]

        applied_migrations = MigrationList()
        applied_migrations.add_migration_info(app_label='tests',
                                              name='0002_add_field')
        record_applied_migrations(connection=connection,
                                  migrations=applied_migrations)

        custom_migrations = MigrationList()
        custom_migrations.add_migration(
            InitialMigration('0001_initial', 'tests'))
        custom_migrations.add_migration(
            AddFieldMigration('0002_add_field', 'tests'))

        executor = MigrationExecutor(connection=connection,
                                     custom_migrations=custom_migrations)

        with self.assertRaises(MigrationHistoryError):
            executor.run_checks()
Beispiel #9
0
    def test_eq(self):
        """Testing MigrationList.__eq__"""
        migration_list1 = MigrationList()
        migration_list2 = MigrationList()

        self.assertEqual(migration_list1, migration_list2)
        self.assertNotEqual(migration_list1, None)
        self.assertNotEqual(migration_list1, ['abc'])
        self.assertNotEqual(migration_list1, 123)

        migration_list1.add_migration_info(app_label='tests',
                                           name='0001_initial')
        self.assertNotEqual(migration_list1, migration_list2)

        migration_list2.add_migration_info(app_label='tests',
                                           name='0001_initial')
        self.assertEqual(migration_list1, migration_list2)

        migration_list2.add_migration_info(app_label='foo',
                                           name='0001_bar')
        self.assertNotEqual(migration_list1, migration_list2)
Beispiel #10
0
    def test_to_targets(self):
        """Testing MigrationList.to_targets"""
        migration_list = MigrationList()
        migration_list.add_migration_info(app_label='tests',
                                          name='0001_initial')
        migration_list.add_migration_info(app_label='foo',
                                          name='0002_bar')

        self.assertEqual(
            migration_list.to_targets(),
            {('tests', '0001_initial'), ('foo', '0002_bar')})
Beispiel #11
0
    def test_apply_migrations(self):
        """Testing apply_migrations"""
        database_state = DatabaseState(db_name=DEFAULT_DB_ALIAS)
        register_models(database_state=database_state,
                        models=[('MigrationTestModel', MigrationTestModel)])

        app_migrations = [
            InitialMigration('0001_initial', 'tests'),
            AddFieldMigration('0002_add_field', 'tests'),
        ]

        targets = [
            ('tests', '0001_initial'),
            ('tests', '0002_add_field'),
        ]

        custom_migrations = MigrationList()
        custom_migrations.add_migration(app_migrations[0])
        custom_migrations.add_migration(app_migrations[1])

        connection = connections[DEFAULT_DB_ALIAS]
        executor = MigrationExecutor(connection,
                                     custom_migrations=custom_migrations)

        migrate_state = apply_migrations(
            executor=executor,
            targets=targets,
            plan=[
                (app_migrations[0], False),
                (app_migrations[1], False),
            ],
            pre_migrate_state=create_pre_migrate_state(executor))
        finalize_migrations(migrate_state)

        # Make sure this is in the database now.
        MigrationTestModel.objects.create(field1=123,
                                          field2='abc',
                                          field3=True)
Beispiel #12
0
    def record_applied_migrations(self,
                                  migration_targets,
                                  database=DEFAULT_DB_ALIAS):
        """Record applied migrations in the database.

        This is a convenience around creating a migration list and then
        recording it in the database.

        Args:
            migration_targets (list of tuple):
                The list of migration targets to store. Each item is a tuple
                in ``(app_label, label)`` form.

            database (unicode, optional):
                The name of the database to save these on.
        """
        assert supports_migrations

        migration_list = MigrationList()
        migration_list.add_migration_targets(migration_targets)

        record_applied_migrations(connection=connections[database],
                                  migrations=migration_list)
Beispiel #13
0
    def test_has_migration_info(self):
        """Testing MigrationList.has_migration_info"""
        migration_list = MigrationList()
        migration_list.add_migration_info(app_label='tests',
                                          name='0001_initial')

        self.assertTrue(migration_list.has_migration_info(
            app_label='tests',
            name='0001_initial'))
        self.assertFalse(migration_list.has_migration_info(
            app_label='tests',
            name='0002_initial'))
        self.assertFalse(migration_list.has_migration_info(
            app_label='foo',
            name='0001_initial'))
Beispiel #14
0
    def test_len(self):
        """Testing MigrationList.__len__"""
        migration_list = MigrationList()
        self.assertEqual(len(migration_list), 0)

        migration_list.add_migration_info(app_label='tests',
                                          name='0001_initial')
        self.assertEqual(len(migration_list), 1)

        migration_list.add_migration_info(app_label='tests',
                                          name='0002_stuff')
        self.assertEqual(len(migration_list), 2)
Beispiel #15
0
    def test_clone(self):
        """Testing MigrationList.clone"""
        migration_list = MigrationList()
        migration_list.add_migration_info(app_label='tests',
                                          name='0001_initial')
        migration_list.add_migration_info(app_label='foo',
                                          name='0002_bar')

        cloned = migration_list.clone()
        self.assertIsNot(migration_list._by_id, cloned._by_id)
        self.assertIsNot(migration_list._by_app_label, cloned._by_app_label)
        self.assertEqual(migration_list._by_id, cloned._by_id)
        self.assertEqual(migration_list._by_app_label, cloned._by_app_label)

        # Change something in the original and make sure the clone isn't
        # affected.
        migration_list._by_id[('tests', '0001_initial')]['name'] = 'changed'
        self.assertNotEqual(migration_list._by_id, cloned._by_id)
        self.assertNotEqual(migration_list._by_app_label, cloned._by_app_label)
Beispiel #16
0
    def test_from_database(self):
        """Testing MigrationList.from_database"""
        connection = connections[DEFAULT_DB_ALIAS]

        applied_migrations = MigrationList()
        applied_migrations.add_migration_info(app_label='tests',
                                              name='0001_initial')
        applied_migrations.add_migration_info(app_label='tests',
                                              name='0002_stuff')
        record_applied_migrations(connection=connection,
                                  migrations=applied_migrations)

        migration_list = MigrationList.from_database(connection)
        self.assertTrue(migration_list.has_migration_info(app_label='tests',
                                                          name='0001_initial'))
        self.assertTrue(migration_list.has_migration_info(app_label='tests',
                                                          name='0002_stuff'))
Beispiel #17
0
    def test_record_applied_migrations(self):
        """Testing record_applied_migrations"""
        connection = connections[DEFAULT_DB_ALIAS]

        # Ideally we'd do an assertNumQueries(2), but MigrationRecorder doesn't
        # cache state and performs repeated queries for the same list of
        # installed table names, followed by new transactions. That might
        # differ depending on the type of database being used.
        migrations = MigrationList()
        migrations.add_migration_info(app_label='tests',
                                      name='0001_initial')
        migrations.add_migration_info(app_label='tests',
                                      name='0002_stuff')

        record_applied_migrations(connection=connection,
                                  migrations=migrations)

        recorder = MigrationRecorder(connection)
        applied_migrations = recorder.applied_migrations()

        self.assertIn(('tests', '0001_initial'), applied_migrations)
        self.assertIn(('tests', '0002_stuff'), applied_migrations)
Beispiel #18
0
    def test_unrecord_applied_migrations(self):
        """Testing unrecord_applied_migrations"""
        connection = connections[DEFAULT_DB_ALIAS]

        migrations = MigrationList()
        migrations.add_migration_info(app_label='tests',
                                      name='0001_initial')
        migrations.add_migration_info(app_label='tests',
                                      name='0002_stuff')

        record_applied_migrations(connection=connection,
                                  migrations=migrations)

        unrecord_applied_migrations(connection=connection,
                                    app_label='tests',
                                    migration_names=['0001_initial',
                                                     '0002_stuff'])

        recorder = MigrationRecorder(connection)
        applied_migrations = recorder.applied_migrations()

        self.assertNotIn(('tests', '0001_initial'), applied_migrations)
        self.assertNotIn(('tests', '0002_stuff'), applied_migrations)
Beispiel #19
0
    def assertAppliedMigrations(self,
                                expected_migration_targets,
                                database=DEFAULT_DB_ALIAS):
        """Assert that applied migrations match expectations.

        Args:
            expected_migration_targets (list of tuple):
                A list of migration targets to compare against the applied
                migrations. Each item is a tuple in ``(app_label, name)``
                form.

            database (unicode, optional):
                The name of the database to query appliedm migrations against.

        Raises:
            AssertionError:
                The lists do not match.
        """
        applied_migrations = MigrationList.from_database(connections[database])

        for app_label, name in expected_migration_targets:
            self.assertTrue(
                applied_migrations.has_migration_info(app_label=app_label,
                                                      name=name))
Beispiel #20
0
    def test_run_checks_with_conflicts(self):
        """Testing MigrationExecutor.run_checks with conflicts"""
        connection = connections[DEFAULT_DB_ALIAS]

        custom_migrations = MigrationList()
        custom_migrations.add_migration(
            InitialMigration('0001_initial', 'tests'))
        custom_migrations.add_migration(
            InitialMigration('0002_also_initial', 'tests'))

        executor = MigrationExecutor(connection=connection,
                                     custom_migrations=custom_migrations)

        message = (
            "Conflicting migrations detected; multiple leaf nodes in the "
            "migration graph: (0001_initial, 0002_also_initial in tests).\n"
            "To fix them run 'python manage.py makemigrations --merge'"
        )

        with self.assertRaisesMessage(MigrationConflictsError, message):
            executor.run_checks()
Beispiel #21
0
    def test_iter(self):
        """Testing MigrationList.__iter__"""
        migration_list = MigrationList()
        migration_list.add_migration_info(app_label='tests',
                                          name='0001_initial')
        migration_list.add_migration_info(app_label='tests',
                                          name='0002_stuff')

        self.assertEqual(
            list(migration_list),
            [
                {
                    'app_label': 'tests',
                    'name': '0001_initial',
                    'migration': None,
                    'recorded_migration': None,
                },
                {
                    'app_label': 'tests',
                    'name': '0002_stuff',
                    'migration': None,
                    'recorded_migration': None,
                },
            ])
Beispiel #22
0
    def test_update(self):
        """Testing MigrationList.update"""
        if supports_migrations:
            migration1 = InitialMigration('0001_initial', 'tests')
            migration2 = AddFieldMigration('0002_add_field', 'tests')
            recorded_migration1 = MigrationRecorder.Migration(
                app='tests',
                name='0001_initial',
                applied=True)
            recorded_migration2 = MigrationRecorder.Migration(
                app='tests',
                name='0002_add_field',
                applied=True)
        else:
            migration1 = None
            migration2 = None
            recorded_migration1 = None
            recorded_migration2 = None

        migration_list1 = MigrationList()
        migration_list1.add_migration_info(
            app_label='tests',
            name='0001_initial',
            migration=migration1,
            recorded_migration=recorded_migration1)
        migration_list1.add_migration_info(
            app_label='tests',
            name='0002_add_field',
            migration=None,
            recorded_migration=None)

        migration_list2 = MigrationList()
        migration_list2.add_migration_info(
            app_label='tests',
            name='0002_add_field',
            migration=migration2,
            recorded_migration=recorded_migration2)
        migration_list2.add_migration_info(
            app_label='foo',
            name='0001_initial')

        migration_list1.update(migration_list2)

        self.assertEqual(
            migration_list1._by_id,
            {
                ('tests', '0001_initial'): {
                    'app_label': 'tests',
                    'name': '0001_initial',
                    'migration': migration1,
                    'recorded_migration': recorded_migration1,
                },
                ('tests', '0002_add_field'): {
                    'app_label': 'tests',
                    'name': '0002_add_field',
                    'migration': migration2,
                    'recorded_migration': recorded_migration2,
                },
                ('foo', '0001_initial'): {
                    'app_label': 'foo',
                    'name': '0001_initial',
                    'migration': None,
                    'recorded_migration': None,
                },
            })
        self.assertEqual(
            migration_list1._by_app_label,
            {
                'foo': [
                    {
                        'app_label': 'foo',
                        'name': '0001_initial',
                        'migration': None,
                        'recorded_migration': None,
                    },
                ],
                'tests': [
                    {
                        'app_label': 'tests',
                        'name': '0001_initial',
                        'migration': migration1,
                        'recorded_migration': recorded_migration1,
                    },
                    {
                        'app_label': 'tests',
                        'name': '0002_add_field',
                        'migration': migration2,
                        'recorded_migration': recorded_migration2,
                    },
                ],
            })
    def _add_migrations(self, graph, migrations_info, leaf_migration_targets,
                        mark_applied=[]):
        """Add migrations to a graph.

        This is a utility for simplifying the additions of a list of
        migrations to a graph, handling the creation of the Django migration
        objects, the formulation of a migration plan, and the recording of
        applied migrations.

        Args:
            graph (django_evolution.utils.graph.EvolutionGraph):
                The graph to add migrations to.

            migrations_info (list of tuple):
                The list of info on migrations to add. Each tuple contains:

                1. The app label
                2. The migration name
                3. The migration class

            leaf_migration_targets (list of tuple):
                The list of final migration targets to migrate to.

            mark_applied (list of tuple, optional):
                The list of migration targets to mark as applied.

        Returns:
            list of tuple:
            The migration plan generated from the migrations.
        """
        migration_list = MigrationList()

        for app_label, name, migration_cls in migrations_info:
            migration_list.add_migration_info(
                app_label=app_label,
                name=name,
                migration=migration_cls(name, app_label))

        connection = connections[DEFAULT_DB_ALIAS]

        if mark_applied:
            mark_applied_list = MigrationList()
            mark_applied_list.add_migration_targets(mark_applied)

            record_applied_migrations(connection, mark_applied_list)
        else:
            mark_applied_list = None

        migration_executor = MigrationExecutor(
            connection=connection,
            custom_migrations=migration_list)
        migration_loader = MigrationLoader(
            connection=connection,
            custom_migrations=migration_list)

        migration_plan = \
            migration_executor.migration_plan(leaf_migration_targets)
        migration_loader.build_graph()

        graph.add_migration_plan(migration_plan=migration_plan,
                                 migration_graph=migration_loader.graph)

        if mark_applied_list:
            graph.mark_migrations_applied(mark_applied_list)

        return migration_plan
Beispiel #24
0
def get_app_upgrade_info(app,
                         scan_evolutions=True,
                         simulate_applied=False,
                         database=None):
    """Return the upgrade information to use for a given app.

    This will determine if the app should be using Django Evolution or
    Django Migrations for any schema upgrades.

    If an ``evolutions`` module is found, then this will determine the method
    to be :py:attr:`UpgradeMethod.EVOLUTIONS
    <django_evolution.consts.UpgradeMethod.EVOLUTIONS>`, unless the app has
    been moved over to using Migrations.

    If instead there's a ``migrations`` module, then this will determine
    the method to be :py:attr:`UpgradeMethod.MIGRATIONS
    <django_evolution.consts.UpgradeMethod.MIGRATIONS>`.

    Otherwise, this will return ``None``, indicating that no established
    method has been chosen. This allows a determination to be made later,
    based on the Django version or the consumer's choice.

    Note that this may return that migrations are the preferred method for
    an app even on versions of Django that do not support migrations. It's
    up to the caller to handle this however it chooses.

    Args:
        app (module):
            The app module to determine the upgrade method for.

        scan_evolutions (bool, optional):
            Whether to scan evolutions for the app to determine the current
            upgrade method.

        simulate_applied (bool, optional):
            Return the upgrade method based on the state of the app if all
            mutations had been applied. This is useful for generating end
            state signatures.

            This is ignored if passing ``scan_evolutions=False``.

        database (unicode, optional):
            The database to use for accessing stored evolution and migration
            information.

    Returns:
        dict:
        A dictionary of information containing the following keys:

        ``applied_migrations`` (:py:class:`~django_evolution.utils.migrations.MigrationList`):
            A list of migrations that have been applied to this app through
            any mutations. This will only be present if the upgrade method is
            set to use migrations and if running on a version of Django that
            supports migrations.

        ``has_evolutions`` (:py:class:`bool`):
            Whether there are any evolutions for this app. This may come from
            the app, project, or Django Evolution.

        ``has_migrations`` (:py:class:`bool`):
            Whether there are any migrations for this app.

        ``upgrade_method`` (:py:class:`unicode`):
            The upgrade method. This will be a value from
            :py:class:`~django_evolution.consts.UpgradeMethod`, or ``None``
            if a clear determination could not be made.
    """
    # Avoids a nasty circular import. Util modules should always be
    # importable, so we compensate here.
    from django_evolution.mutations import MoveToDjangoMigrations

    upgrade_method = None
    applied_migrations = None
    has_evolutions = has_evolutions_module(app)
    has_migrations = has_migrations_module(app)

    if has_evolutions:
        # This app made use of Django Evolution. See if we're still using
        # that, or if it's handed control over to Django migrations.
        if scan_evolutions:
            if simulate_applied:
                evolutions = None
            else:
                evolutions = get_applied_evolutions(app, database=database)

            mutations = get_app_mutations(app=app, evolution_labels=evolutions)

            for mutation in reversed(mutations):
                if isinstance(mutation, MoveToDjangoMigrations):
                    app_label = get_app_label(app)
                    upgrade_method = UpgradeMethod.MIGRATIONS

                    applied_migrations = MigrationList()

                    for name in mutation.mark_applied:
                        applied_migrations.add_migration_info(
                            app_label=app_label, name=name)

                    break

        if not upgrade_method:
            upgrade_method = UpgradeMethod.EVOLUTIONS

    if has_migrations:
        if not upgrade_method:
            upgrade_method = UpgradeMethod.MIGRATIONS

        if supports_migrations:
            applied_migrations = MigrationList.from_database(
                connection=connections[database or DEFAULT_DB_ALIAS],
                app_label=get_app_label(app))

            if not applied_migrations:
                applied_migrations = None

    return {
        'applied_migrations': applied_migrations,
        'has_evolutions': has_evolutions,
        'has_migrations': has_migrations,
        'upgrade_method': upgrade_method,
    }
Beispiel #25
0
    def test_sub(self):
        """Testing MigrationList.__sub__"""
        migration_list1 = MigrationList()
        migration_list1.add_migration_info(app_label='tests',
                                           name='0001_initial')
        migration_list1.add_migration_info(app_label='tests',
                                           name='0002_stuff')

        migration_list2 = MigrationList()
        migration_list2.add_migration_info(app_label='tests',
                                           name='0001_initial')
        migration_list2.add_migration_info(app_label='foo',
                                           name='0002_bar')

        new_migration_list = migration_list1 - migration_list2

        self.assertEqual(
            new_migration_list._by_id,
            {
                ('tests', '0002_stuff'): {
                    'app_label': 'tests',
                    'name': '0002_stuff',
                    'migration': None,
                    'recorded_migration': None,
                },
            })
        self.assertEqual(
            new_migration_list._by_app_label,
            {
                'tests': [
                    {
                        'app_label': 'tests',
                        'name': '0002_stuff',
                        'migration': None,
                        'recorded_migration': None,
                    },
                ],
            })

        # Make sure there's no cross-contamination.
        self.assertNotEqual(new_migration_list._by_id, migration_list1._by_id)
        self.assertNotEqual(new_migration_list._by_id, migration_list2._by_id)
        self.assertNotEqual(migration_list1._by_id, migration_list2._by_id)