Fixed #23407 -- Extended coverage of makemigrations --noinput option.
Changed --noinput option in makemigrations to suppress all user prompts, not just when combined with --merge.
This commit is contained in:
parent
794c3f74c3
commit
e272904ff7
|
@ -9,6 +9,7 @@ from django.db.migrations.autodetector import MigrationAutodetector
|
||||||
from django.db.migrations.loader import MigrationLoader
|
from django.db.migrations.loader import MigrationLoader
|
||||||
from django.db.migrations.questioner import (
|
from django.db.migrations.questioner import (
|
||||||
InteractiveMigrationQuestioner, MigrationQuestioner,
|
InteractiveMigrationQuestioner, MigrationQuestioner,
|
||||||
|
NonInteractiveMigrationQuestioner,
|
||||||
)
|
)
|
||||||
from django.db.migrations.state import ProjectState
|
from django.db.migrations.state import ProjectState
|
||||||
from django.db.migrations.writer import MigrationWriter
|
from django.db.migrations.writer import MigrationWriter
|
||||||
|
@ -93,11 +94,15 @@ class Command(BaseCommand):
|
||||||
if self.merge and conflicts:
|
if self.merge and conflicts:
|
||||||
return self.handle_merge(loader, conflicts)
|
return self.handle_merge(loader, conflicts)
|
||||||
|
|
||||||
|
if self.interactive:
|
||||||
|
questioner = InteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run)
|
||||||
|
else:
|
||||||
|
questioner = NonInteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run)
|
||||||
# Set up autodetector
|
# Set up autodetector
|
||||||
autodetector = MigrationAutodetector(
|
autodetector = MigrationAutodetector(
|
||||||
loader.project_state(),
|
loader.project_state(),
|
||||||
ProjectState.from_apps(apps),
|
ProjectState.from_apps(apps),
|
||||||
InteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run),
|
questioner,
|
||||||
)
|
)
|
||||||
|
|
||||||
# If they want to make an empty migration, make one for each app
|
# If they want to make an empty migration, make one for each app
|
||||||
|
|
|
@ -180,3 +180,14 @@ class InteractiveMigrationQuestioner(MigrationQuestioner):
|
||||||
"Do you want to merge these migration branches? [y/N]",
|
"Do you want to merge these migration branches? [y/N]",
|
||||||
False,
|
False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NonInteractiveMigrationQuestioner(MigrationQuestioner):
|
||||||
|
|
||||||
|
def ask_not_null_addition(self, field_name, model_name):
|
||||||
|
# We can't ask the user, so act like the user aborted.
|
||||||
|
sys.exit(3)
|
||||||
|
|
||||||
|
def ask_not_null_alteration(self, field_name, model_name):
|
||||||
|
# We can't ask the user, so set as not provided.
|
||||||
|
return NOT_PROVIDED
|
||||||
|
|
|
@ -649,6 +649,11 @@ 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
|
to the app(s) specified and any dependencies needed (the table at the other end
|
||||||
of a ``ForeignKey``, for example).
|
of a ``ForeignKey``, for example).
|
||||||
|
|
||||||
|
.. versionchanged:: 1.9
|
||||||
|
|
||||||
|
The ``--noinput`` option may be provided to suppress all user prompts. If a suppressed
|
||||||
|
prompt cannot be resolved automatically, the command will exit with error code 3.
|
||||||
|
|
||||||
.. django-admin-option:: --empty
|
.. django-admin-option:: --empty
|
||||||
|
|
||||||
The ``--empty`` option will cause ``makemigrations`` to output an empty
|
The ``--empty`` option will cause ``makemigrations`` to output an empty
|
||||||
|
@ -666,9 +671,7 @@ written.
|
||||||
|
|
||||||
.. django-admin-option:: --merge
|
.. django-admin-option:: --merge
|
||||||
|
|
||||||
The ``--merge`` option enables fixing of migration conflicts. The
|
The ``--merge`` option enables fixing of migration conflicts.
|
||||||
:djadminopt:`--noinput` option may be provided to suppress user prompts during
|
|
||||||
a merge.
|
|
||||||
|
|
||||||
.. django-admin-option:: --name, -n
|
.. django-admin-option:: --name, -n
|
||||||
|
|
||||||
|
|
|
@ -531,6 +531,80 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
questioner.input = old_input
|
questioner.input = old_input
|
||||||
self.assertIn("Created new merge migration", force_text(out.getvalue()))
|
self.assertIn("Created new merge migration", force_text(out.getvalue()))
|
||||||
|
|
||||||
|
def test_makemigrations_non_interactive_not_null_addition(self):
|
||||||
|
"""
|
||||||
|
Tests that non-interactive makemigrations fails when a default is missing on a new not-null field.
|
||||||
|
"""
|
||||||
|
class SillyModel(models.Model):
|
||||||
|
silly_field = models.BooleanField(default=False)
|
||||||
|
silly_int = models.IntegerField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = "migrations"
|
||||||
|
|
||||||
|
out = six.StringIO()
|
||||||
|
with self.assertRaises(SystemExit):
|
||||||
|
with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
|
||||||
|
call_command("makemigrations", "migrations", interactive=False, stdout=out)
|
||||||
|
|
||||||
|
def test_makemigrations_non_interactive_not_null_alteration(self):
|
||||||
|
"""
|
||||||
|
Tests that non-interactive makemigrations fails when a default is missing on a field changed to not-null.
|
||||||
|
"""
|
||||||
|
class Author(models.Model):
|
||||||
|
name = models.CharField(max_length=255)
|
||||||
|
slug = models.SlugField()
|
||||||
|
age = models.IntegerField(default=0)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = "migrations"
|
||||||
|
|
||||||
|
out = six.StringIO()
|
||||||
|
try:
|
||||||
|
with self.temporary_migration_module(module="migrations.test_migrations"):
|
||||||
|
call_command("makemigrations", "migrations", interactive=False, stdout=out)
|
||||||
|
except CommandError:
|
||||||
|
self.fail("Makemigrations failed while running non-interactive questioner.")
|
||||||
|
self.assertIn("Alter field slug on author", force_text(out.getvalue()))
|
||||||
|
|
||||||
|
def test_makemigrations_non_interactive_no_model_rename(self):
|
||||||
|
"""
|
||||||
|
Makes sure that makemigrations adds and removes a possible model rename in non-interactive mode.
|
||||||
|
"""
|
||||||
|
class RenamedModel(models.Model):
|
||||||
|
silly_field = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = "migrations"
|
||||||
|
|
||||||
|
out = six.StringIO()
|
||||||
|
try:
|
||||||
|
with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
|
||||||
|
call_command("makemigrations", "migrations", interactive=False, stdout=out)
|
||||||
|
except CommandError:
|
||||||
|
self.fail("Makemigrations failed while running non-interactive questioner")
|
||||||
|
self.assertIn("Delete model SillyModel", force_text(out.getvalue()))
|
||||||
|
self.assertIn("Create model RenamedModel", force_text(out.getvalue()))
|
||||||
|
|
||||||
|
def test_makemigrations_non_interactive_no_field_rename(self):
|
||||||
|
"""
|
||||||
|
Makes sure that makemigrations adds and removes a possible field rename in non-interactive mode.
|
||||||
|
"""
|
||||||
|
class SillyModel(models.Model):
|
||||||
|
silly_rename = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
app_label = "migrations"
|
||||||
|
|
||||||
|
out = six.StringIO()
|
||||||
|
try:
|
||||||
|
with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
|
||||||
|
call_command("makemigrations", "migrations", interactive=False, stdout=out)
|
||||||
|
except CommandError:
|
||||||
|
self.fail("Makemigrations failed while running non-interactive questioner")
|
||||||
|
self.assertIn("Remove field silly_field from sillymodel", force_text(out.getvalue()))
|
||||||
|
self.assertIn("Add field silly_rename to sillymodel", force_text(out.getvalue()))
|
||||||
|
|
||||||
def test_makemigrations_handle_merge(self):
|
def test_makemigrations_handle_merge(self):
|
||||||
"""
|
"""
|
||||||
Makes sure that makemigrations properly merges the conflicting migrations with --noinput.
|
Makes sure that makemigrations properly merges the conflicting migrations with --noinput.
|
||||||
|
|
Loading…
Reference in New Issue