From 0d7929266ec9d8f6bcf9e41a40b281259cba6a79 Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Fri, 26 Aug 2016 14:04:12 -0700 Subject: [PATCH] Fixed #25109 -- Stopped silencing explicitly specified migration modules import errors. Thanks Tim for the review. --- django/db/migrations/loader.py | 14 ++++++++++---- django/db/migrations/questioner.py | 2 +- django/db/migrations/writer.py | 2 +- tests/migrations/test_loader.py | 16 ++++++++++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/django/db/migrations/loader.py b/django/db/migrations/loader.py index 262378d1dc..c78aaed573 100644 --- a/django/db/migrations/loader.py +++ b/django/db/migrations/loader.py @@ -54,11 +54,16 @@ class MigrationLoader(object): @classmethod def migrations_module(cls, app_label): + """ + Return the path to the migrations module for the specified app_label + and a boolean indicating if the module is specified in + settings.MIGRATION_MODULE. + """ if app_label in settings.MIGRATION_MODULES: - return settings.MIGRATION_MODULES[app_label] + return settings.MIGRATION_MODULES[app_label], True else: app_package_name = apps.get_app_config(app_label).name - return '%s.%s' % (app_package_name, MIGRATIONS_MODULE_NAME) + return '%s.%s' % (app_package_name, MIGRATIONS_MODULE_NAME), False def load_disk(self): """ @@ -69,7 +74,7 @@ class MigrationLoader(object): self.migrated_apps = set() for app_config in apps.get_app_configs(): # Get the migrations module directory - module_name = self.migrations_module(app_config.label) + module_name, explicit = self.migrations_module(app_config.label) if module_name is None: self.unmigrated_apps.add(app_config.label) continue @@ -79,7 +84,8 @@ class MigrationLoader(object): except ImportError as e: # I hate doing this, but I don't want to squash other import errors. # Might be better to try a directory check directly. - if "No module named" in str(e) and MIGRATIONS_MODULE_NAME in str(e): + if ((explicit and self.ignore_no_migrations) or ( + not explicit and "No module named" in str(e) and MIGRATIONS_MODULE_NAME in str(e))): self.unmigrated_apps.add(app_config.label) continue raise diff --git a/django/db/migrations/questioner.py b/django/db/migrations/questioner.py index 593e0ace3b..df08508a10 100644 --- a/django/db/migrations/questioner.py +++ b/django/db/migrations/questioner.py @@ -37,7 +37,7 @@ class MigrationQuestioner(object): app_config = apps.get_app_config(app_label) except LookupError: # It's a fake app. return self.defaults.get("ask_initial", False) - migrations_import_path = MigrationLoader.migrations_module(app_config.label) + migrations_import_path, _ = MigrationLoader.migrations_module(app_config.label) if migrations_import_path is None: # It's an application with migrations disabled. return self.defaults.get("ask_initial", False) diff --git a/django/db/migrations/writer.py b/django/db/migrations/writer.py index 137f83dbc0..7c39cdc931 100644 --- a/django/db/migrations/writer.py +++ b/django/db/migrations/writer.py @@ -221,7 +221,7 @@ class MigrationWriter(object): @property def basedir(self): - migrations_package_name = MigrationLoader.migrations_module(self.migration.app_label) + migrations_package_name, _ = MigrationLoader.migrations_module(self.migration.app_label) if migrations_package_name is None: raise ValueError( diff --git a/tests/migrations/test_loader.py b/tests/migrations/test_loader.py index b8c2cd8142..5b31fcbd2c 100644 --- a/tests/migrations/test_loader.py +++ b/tests/migrations/test_loader.py @@ -205,6 +205,22 @@ class LoaderTests(TestCase): self.assertEqual(migration_loader.migrated_apps, set()) self.assertEqual(migration_loader.unmigrated_apps, {'migrated_app'}) + @override_settings( + INSTALLED_APPS=['migrations.migrations_test_apps.migrated_app'], + MIGRATION_MODULES={'migrated_app': 'missing-module'}, + ) + def test_explicit_missing_module(self): + """ + If a MIGRATION_MODULES override points to a missing module, the error + raised during the importation attempt should be propagated unless + `ignore_no_migrations=True`. + """ + with self.assertRaisesMessage(ImportError, 'missing-module'): + migration_loader = MigrationLoader(connection) + migration_loader = MigrationLoader(connection, ignore_no_migrations=True) + self.assertEqual(migration_loader.migrated_apps, set()) + self.assertEqual(migration_loader.unmigrated_apps, {'migrated_app'}) + @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_squashed"}) def test_loading_squashed(self): "Tests loading a squashed migration"