Example #1
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'))
Example #2
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))
Example #3
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,
    }