From fbb684d95ed71487fe16135321d59ddb043ee903 Mon Sep 17 00:00:00 2001 From: Huu Nguyen Date: Thu, 19 Jun 2014 16:50:01 -0700 Subject: [PATCH] Fixed #22862 -- Added --noinput option to makemigrations. Thanks artortenburger for the report. --- .../management/commands/makemigrations.py | 4 +- docs/ref/django-admin.txt | 2 + tests/migrations/test_commands.py | 47 +++++++++++++------ 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/django/core/management/commands/makemigrations.py b/django/core/management/commands/makemigrations.py index 9f20743869a..42e57cd17de 100644 --- a/django/core/management/commands/makemigrations.py +++ b/django/core/management/commands/makemigrations.py @@ -25,6 +25,8 @@ class Command(BaseCommand): help="Enable fixing of migration conflicts.") parser.add_argument('--empty', action='store_true', dest='empty', default=False, help="Create an empty migration.") + parser.add_argument('--noinput', action='store_false', dest='interactive', default=True, + help='Tells Django to NOT prompt the user for input of any kind.') def handle(self, *app_labels, **options): @@ -154,7 +156,7 @@ class Command(BaseCommand): if self.interactive: questioner = InteractiveMigrationQuestioner() else: - questioner = MigrationQuestioner() + questioner = MigrationQuestioner(defaults={'ask_merge': True}) for app_label, migration_names in conflicts.items(): # Grab out the migrations in question, and work out their # common ancestor. diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index cdc312d05c5..f47c1967cd6 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -652,6 +652,8 @@ Providing one or more app names as arguments will limit the migrations created to the app(s) specified and any dependencies needed (the table at the other end of a ``ForeignKey``, for example). +The :djadminopt:`--noinput` option may be provided to suppress all user prompts. + .. django-admin-option:: --empty The ``--empty`` option will cause ``makemigrations`` to output an empty diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index c223b5f4897..6ba92f87dd8 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -231,19 +231,6 @@ class MakeMigrationsTests(MigrationTestBase): with self.assertRaises(CommandError): call_command("makemigrations") - @override_system_checks([]) - @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_conflict"}) - def test_makemigrations_merge_basic(self): - """ - Makes sure that makemigrations doesn't error if you ask for - merge mode with a conflict present. Doesn't test writing of the merge - file, as that requires temp directories. - """ - try: - call_command("makemigrations", merge=True, verbosity=0) - except CommandError: - self.fail("Makemigrations errored in merge mode with conflicts") - @override_system_checks([]) @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"}) def test_makemigrations_merge_no_conflict(self): @@ -386,13 +373,18 @@ class MakeMigrationsTests(MigrationTestBase): @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_conflict"}) def test_makemigrations_handle_merge(self): """ - Makes sure that makemigrations properly merges the conflicting migrations. + Makes sure that makemigrations properly merges the conflicting migrations with --noinput. """ stdout = six.StringIO() - call_command("makemigrations", "migrations", merge=True, stdout=stdout) + call_command("makemigrations", "migrations", merge=True, interactive=False, stdout=stdout) self.assertIn("Merging migrations", stdout.getvalue()) self.assertIn("Branch 0002_second", stdout.getvalue()) self.assertIn("Branch 0002_conflicting_second", stdout.getvalue()) + merge_file = os.path.join(self.test_dir, 'test_migrations_conflict', '0003_merge.py') + self.assertTrue(os.path.exists(merge_file)) + os.remove(merge_file) + self.assertFalse(os.path.exists(merge_file)) + self.assertIn("Created new merge migration", stdout.getvalue()) @override_system_checks([]) @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_no_default"}) @@ -469,3 +461,28 @@ class MakeMigrationsTests(MigrationTestBase): self.assertTrue(os.path.isfile(os.path.join(self.test_dir, "test_migrations_path_doesnt_exist", "foo", "bar", "0001_initial.py"))) + + @override_system_checks([]) + @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_conflict"}) + def test_makemigrations_interactive_by_default(self): + """ + Makes sure that the user is prompted to merge by default if there are + conflicts and merge is True. Answer negative to differentiate it from + behavior when --noinput is specified. + """ + # Monkeypatch interactive questioner to auto reject + old_input = questioner.input + questioner.input = lambda _: "N" + stdout = six.StringIO() + try: + call_command("makemigrations", "migrations", merge=True, stdout=stdout) + merge_file = os.path.join(self.test_dir, 'test_migrations_conflict', '0003_merge.py') + # This will fail if interactive is False by default + self.assertFalse(os.path.exists(merge_file)) + except CommandError: + self.fail("Makemigrations failed while running interactive questioner") + finally: + questioner.input = old_input + if os.path.exists(merge_file): + os.remove(merge_file) + self.assertNotIn("Created new merge migration", stdout.getvalue())