Example #1
0
    def test_exclude_migration_tests(self):
        m = Migration("0002_add_new_not_null_field", "app_add_not_null_column")

        linter = MigrationLinter(exclude_migration_tests=[], database="mysql")
        linter.lint_migration(m)
        self.assertTrue(linter.has_errors)

        linter = MigrationLinter(exclude_migration_tests=["NOT_NULL"],
                                 database="mysql")
        linter.lint_migration(m)
        self.assertFalse(linter.has_errors)
    def test_multiple_linters(self):
        l1 = MigrationLinter(fixtures.ADD_NOT_NULL_COLUMN_PROJECT)
        l2 = MigrationLinter(fixtures.RENAME_COLUMN_PROJECT)
        l3 = MigrationLinter(fixtures.CORRECT_PROJECT)

        l1.lint_migration(
            Migration(
                os.path.join(
                    fixtures.ADD_NOT_NULL_COLUMN_PROJECT,
                    'test_app/migrations/0002_add_new_not_null_field.py')))
        l2.lint_migration(
            Migration(
                os.path.join(fixtures.RENAME_COLUMN_PROJECT,
                             'test_app/migrations/0002_rename_column.py')))
        l3.lint_migration(
            Migration(
                os.path.join(fixtures.CORRECT_PROJECT,
                             'test_app1/migrations/0001_initial.py')))
        l3.lint_migration(
            Migration(
                os.path.join(fixtures.CORRECT_PROJECT,
                             'test_app1/migrations/0002_a_new_null_field.py')))

        self.assertTrue(l1.has_errors)
        self.assertTrue(l2.has_errors)
        self.assertFalse(l3.has_errors)

        self.assertEqual(l1.nb_total, 1)
        self.assertEqual(l2.nb_total, 1)
        self.assertEqual(l3.nb_total, 2)
class DataMigrationDetectionTestCase(unittest.TestCase):
    def setUp(self, *args, **kwargs):
        self.test_project_path = os.path.dirname(settings.BASE_DIR)
        self.linter = MigrationLinter(
            self.test_project_path,
            include_apps=fixtures.DATA_MIGRATIONS,
        )

    def test_reverse_data_migration(self):
        self.assertEqual(0, self.linter.nb_warnings)
        reverse_migration = self.linter.migration_loader.disk_migrations[(
            "app_data_migrations", "0002_missing_reverse")]
        self.linter.lint_migration(reverse_migration)

        self.assertEqual(1, self.linter.nb_warnings)
        self.assertFalse(self.linter.has_errors)

    def test_reverse_data_migration_ignore(self):
        reverse_migration = self.linter.migration_loader.disk_migrations[(
            "app_data_migrations", "0003_incorrect_arguments")]
        self.linter.lint_migration(reverse_migration)

        self.assertEqual(1, self.linter.nb_warnings)
        self.assertFalse(self.linter.has_errors)

    def test_exclude_warning_from_test(self):
        self.linter = MigrationLinter(
            self.test_project_path,
            include_apps=fixtures.DATA_MIGRATIONS,
            exclude_migration_tests=("RUNPYTHON_REVERSIBLE", ),
        )

        reverse_migration = self.linter.migration_loader.disk_migrations[(
            "app_data_migrations", "0002_missing_reverse")]
        self.linter.lint_migration(reverse_migration)

        self.assertEqual(0, self.linter.nb_warnings)
        self.assertEqual(1, self.linter.nb_valid)
        self.assertFalse(self.linter.has_errors)

    def test_warnings_as_errors(self):
        self.linter = MigrationLinter(
            self.test_project_path,
            include_apps=fixtures.DATA_MIGRATIONS,
            warnings_as_errors=True,
        )

        reverse_migration = self.linter.migration_loader.disk_migrations[(
            "app_data_migrations", "0003_incorrect_arguments")]
        self.linter.lint_migration(reverse_migration)

        self.assertEqual(0, self.linter.nb_warnings)
        self.assertEqual(1, self.linter.nb_erroneous)
        self.assertTrue(self.linter.has_errors)
Example #4
0
    def write_migration_files(self, changes):
        super(Command, self).write_migration_files(changes)

        if (
            not getattr(settings, "MIGRATION_LINTER_OVERRIDE_MAKEMIGRATIONS", False)
            and not self.lint
        ):
            return

        if self.dry_run:
            """
            Since we rely on the 'sqlmigrate' to lint the migrations, we can only
            lint if the migration files have been generated. Since the 'dry-run'
            option won't generate the files, we cannot lint migrations.
            """
            return

        should_keep_migration = (
            ask_should_keep_migration
            if self.interactive
            else default_should_keep_migration
        )

        # Lint migrations
        linter = MigrationLinter(
            path=os.environ["DJANGO_SETTINGS_MODULE"],
            database=self.database,
            no_cache=True,
            exclude_migration_tests=self.exclude_migrations_tests,
            warnings_as_errors=self.warnings_as_errors,
        )

        for app_label, app_migrations in changes.items():
            if self.verbosity >= 1:
                self.stdout.write(
                    self.style.MIGRATE_HEADING("Linting for '%s':" % app_label) + "\n"
                )

            for migration in app_migrations:
                linter.lint_migration(migration)
                if linter.has_errors:
                    if not should_keep_migration():
                        self.delete_migration(migration)
                linter.reset_counters()
    def test_has_errors(self):
        project_path = fixtures.MULTI_COMMIT_PROJECT
        linter = MigrationLinter(project_path)
        self.assertFalse(linter.has_errors)

        linter.lint_migration('test_app', '0001')
        self.assertFalse(linter.has_errors)

        linter.lint_migration('test_app', '0002')
        self.assertTrue(linter.has_errors)

        linter.lint_migration('test_app', '0001')
        self.assertTrue(linter.has_errors)
    def test_has_errors(self):
        linter = MigrationLinter()
        self.assertFalse(linter.has_errors)

        m = Migration("0001_create_table", "app_add_not_null_column")
        linter.lint_migration(m)
        self.assertFalse(linter.has_errors)

        m = Migration("0002_add_new_not_null_field", "app_add_not_null_column")
        linter.lint_migration(m)
        self.assertTrue(linter.has_errors)

        m = Migration("0001_create_table", "app_add_not_null_column")
        linter.lint_migration(m)
        self.assertTrue(linter.has_errors)
    def test_has_errors(self):
        project_path = fixtures.MULTI_COMMIT_PROJECT
        linter = MigrationLinter(project_path)
        self.assertFalse(linter.has_errors)

        m = Migration(os.path.join(project_path, 'test_app/migrations/0001_create_table.py'))
        linter.lint_migration(m)
        self.assertFalse(linter.has_errors)

        m = Migration(os.path.join(project_path, 'test_app/migrations/0002_add_new_not_null_field.py'))
        linter.lint_migration(m)
        self.assertTrue(linter.has_errors)

        m = Migration(os.path.join(project_path, 'test_app/migrations/0001_create_table.py'))
        linter.lint_migration(m)
        self.assertTrue(linter.has_errors)
    def test_multiple_linters(self):
        l1 = MigrationLinter(fixtures.ADD_NOT_NULL_COLUMN_PROJECT)
        l2 = MigrationLinter(fixtures.RENAME_COLUMN_PROJECT)
        l3 = MigrationLinter(fixtures.CORRECT_PROJECT)

        l1.lint_migration('test_app', '0002')
        l2.lint_migration('test_app', '0002')
        l3.lint_migration('test_app1', '0001')
        l3.lint_migration('test_app1', '0002')

        self.assertTrue(l1.has_errors)
        self.assertTrue(l2.has_errors)
        self.assertFalse(l3.has_errors)

        self.assertEqual(l1.nb_total, 1)
        self.assertEqual(l2.nb_total, 1)
        self.assertEqual(l3.nb_total, 2)
class DataMigrationDetectionTestCase(unittest.TestCase):
    def setUp(self, *args, **kwargs):
        self.test_project_path = os.path.dirname(settings.BASE_DIR)
        self.linter = MigrationLinter(
            self.test_project_path,
            include_apps=fixtures.DATA_MIGRATIONS,
        )

    def test_reverse_data_migration(self):
        self.assertEqual(0, self.linter.nb_warnings)
        reverse_migration = self.linter.migration_loader.disk_migrations[
            ("app_data_migrations", "0002_missing_reverse")
        ]
        self.linter.lint_migration(reverse_migration)

        self.assertEqual(1, self.linter.nb_warnings)
        self.assertFalse(self.linter.has_errors)

    def test_reverse_data_migration_ignore(self):
        reverse_migration = self.linter.migration_loader.disk_migrations[
            ("app_data_migrations", "0003_incorrect_arguments")
        ]
        self.linter.lint_migration(reverse_migration)

        self.assertEqual(1, self.linter.nb_warnings)
        self.assertFalse(self.linter.has_errors)

    def test_exclude_warning_from_test(self):
        self.linter = MigrationLinter(
            self.test_project_path,
            include_apps=fixtures.DATA_MIGRATIONS,
            exclude_migration_tests=("REVERSIBLE_DATA_MIGRATION",),
        )

        reverse_migration = self.linter.migration_loader.disk_migrations[
            ("app_data_migrations", "0002_missing_reverse")
        ]
        self.linter.lint_migration(reverse_migration)

        self.assertEqual(0, self.linter.nb_warnings)
        self.assertEqual(1, self.linter.nb_valid)
        self.assertFalse(self.linter.has_errors)

    def test_warnings_as_errors(self):
        self.linter = MigrationLinter(
            self.test_project_path,
            include_apps=fixtures.DATA_MIGRATIONS,
            warnings_as_errors=True,
        )

        reverse_migration = self.linter.migration_loader.disk_migrations[
            ("app_data_migrations", "0003_incorrect_arguments")
        ]
        self.linter.lint_migration(reverse_migration)

        self.assertEqual(0, self.linter.nb_warnings)
        self.assertEqual(1, self.linter.nb_erroneous)
        self.assertTrue(self.linter.has_errors)

    def test_missing_get_model_import(self):
        def incorrect_importing_model_forward(apps, schema_editor):
            from tests.test_project.app_data_migrations.models import MyModel

            MyModel.objects.filter(id=1).first()

        issues = MigrationLinter.get_data_migration_model_import_issues(
            incorrect_importing_model_forward
        )
        self.assertEqual(1, len(issues))

    def test_correct_get_model_import(self):
        def correct_importing_model_forward(apps, schema_editor):
            MyModel = apps.get_model("app_data_migrations", "MyModel")
            MyVeryLongLongLongModel = apps.get_model(
                "app_data_migrations", "MyVeryLongLongLongModel"
            )

            MyModel.objects.filter(id=1).first()
            MyVeryLongLongLongModel.objects.filter(id=1).first()

        issues = MigrationLinter.get_data_migration_model_import_issues(
            correct_importing_model_forward
        )
        self.assertEqual(0, len(issues))