summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDakota Hawkins <dakotahawkins@users.noreply.github.com>2018-12-19 06:41:31 -0500
committerCarlton Gibson <carlton.gibson@noumenal.es>2018-12-19 12:41:31 +0100
commit8d3147e130c4e5638fceb1e6125c040362ce12e8 (patch)
tree3e17b6ed50be3466ced3ec73a2745f37f994cebb
parentb514dc14f4e1c364341f5931b354e83ef15ee12d (diff)
Fixed #30031 -- Added --no-header option to makemigrations/squashmigrations.
-rw-r--r--django/core/management/commands/makemigrations.py9
-rw-r--r--django/core/management/commands/squashmigrations.py7
-rw-r--r--django/db/migrations/writer.py22
-rw-r--r--docs/ref/django-admin.txt12
-rw-r--r--docs/releases/2.2.txt4
-rw-r--r--tests/migrations/test_writer.py23
6 files changed, 58 insertions, 19 deletions
diff --git a/django/core/management/commands/makemigrations.py b/django/core/management/commands/makemigrations.py
index cdccb8e9b3..5782b58398 100644
--- a/django/core/management/commands/makemigrations.py
+++ b/django/core/management/commands/makemigrations.py
@@ -49,6 +49,10 @@ class Command(BaseCommand):
help="Use this name for migration file(s).",
)
parser.add_argument(
+ '--no-header', action='store_false', dest='include_header',
+ help='Do not add header comments to new migration file(s).',
+ )
+ parser.add_argument(
'--check', action='store_true', dest='check_changes',
help='Exit with a non-zero status if model changes are missing migrations.',
)
@@ -63,6 +67,7 @@ class Command(BaseCommand):
self.migration_name = options['name']
if self.migration_name and not self.migration_name.isidentifier():
raise CommandError('The migration name must be a valid Python identifier.')
+ self.include_header = options['include_header']
check_changes = options['check_changes']
# Make sure the app they asked for exists
@@ -188,7 +193,7 @@ class Command(BaseCommand):
self.stdout.write(self.style.MIGRATE_HEADING("Migrations for '%s':" % app_label) + "\n")
for migration in app_migrations:
# Describe the migration
- writer = MigrationWriter(migration)
+ writer = MigrationWriter(migration, self.include_header)
if self.verbosity >= 1:
# Display a relative path if it's below the current working
# directory, or an absolute path otherwise.
@@ -288,7 +293,7 @@ class Command(BaseCommand):
self.migration_name or ("merge_%s" % get_migration_name_timestamp())
)
new_migration = subclass(migration_name, app_label)
- writer = MigrationWriter(new_migration)
+ writer = MigrationWriter(new_migration, self.include_header)
if not self.dry_run:
# Write the merge migrations file to the disk
diff --git a/django/core/management/commands/squashmigrations.py b/django/core/management/commands/squashmigrations.py
index ee91241369..4a0ab6af83 100644
--- a/django/core/management/commands/squashmigrations.py
+++ b/django/core/management/commands/squashmigrations.py
@@ -37,6 +37,10 @@ class Command(BaseCommand):
'--squashed-name',
help='Sets the name of the new squashed migration.',
)
+ parser.add_argument(
+ '--no-header', action='store_false', dest='include_header',
+ help='Do not add a header comment to the new squashed migration.',
+ )
def handle(self, **options):
@@ -47,6 +51,7 @@ class Command(BaseCommand):
migration_name = options['migration_name']
no_optimize = options['no_optimize']
squashed_name = options['squashed_name']
+ include_header = options['include_header']
# Validate app_label.
try:
apps.get_app_config(app_label)
@@ -178,7 +183,7 @@ class Command(BaseCommand):
new_migration.initial = True
# Write out the new migration file
- writer = MigrationWriter(new_migration)
+ writer = MigrationWriter(new_migration, include_header)
with open(writer.path, "w", encoding='utf-8') as fh:
fh.write(writer.as_string())
diff --git a/django/db/migrations/writer.py b/django/db/migrations/writer.py
index d056e00646..6a62b4cbf4 100644
--- a/django/db/migrations/writer.py
+++ b/django/db/migrations/writer.py
@@ -132,8 +132,9 @@ class MigrationWriter:
of the migration file from it.
"""
- def __init__(self, migration):
+ def __init__(self, migration, include_header=True):
self.migration = migration
+ self.include_header = include_header
self.needs_manual_porting = False
def as_string(self):
@@ -195,10 +196,13 @@ class MigrationWriter:
if self.migration.replaces:
items['replaces_str'] = "\n replaces = %s\n" % self.serialize(self.migration.replaces)[0]
# Hinting that goes into comment
- items.update(
- version=get_version(),
- timestamp=now().strftime("%Y-%m-%d %H:%M"),
- )
+ if self.include_header:
+ items['migration_header'] = MIGRATION_HEADER_TEMPLATE % {
+ 'version': get_version(),
+ 'timestamp': now().strftime("%Y-%m-%d %H:%M"),
+ }
+ else:
+ items['migration_header'] = ""
if self.migration.initial:
items['initial_str'] = "\n initial = True\n"
@@ -279,10 +283,14 @@ class MigrationWriter:
return serializer_factory(value).serialize()
-MIGRATION_TEMPLATE = """\
+MIGRATION_HEADER_TEMPLATE = """\
# Generated by Django %(version)s on %(timestamp)s
-%(imports)s
+"""
+
+
+MIGRATION_TEMPLATE = """\
+%(migration_header)s%(imports)s
class Migration(migrations.Migration):
%(replaces_str)s%(initial_str)s
diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt
index 19f1d046fe..e8371897e2 100644
--- a/docs/ref/django-admin.txt
+++ b/docs/ref/django-admin.txt
@@ -776,6 +776,12 @@ Enables fixing of migration conflicts.
Allows naming the generated migration(s) instead of using a generated name. The
name must be a valid Python :ref:`identifier <python:identifiers>`.
+.. django-admin-option:: --no-header
+
+.. versionadded:: 2.2
+
+Generate migration files without Django version and timestamp header.
+
.. django-admin-option:: --check
Makes ``makemigrations`` exit with a non-zero status when model changes without
@@ -1156,6 +1162,12 @@ Suppresses all user prompts.
Sets the name of the squashed migration. When omitted, the name is based on the
first and last migration, with ``_squashed_`` in between.
+.. django-admin-option:: --no-header
+
+.. versionadded:: 2.2
+
+Generate squashed migration file without Django version and timestamp header.
+
``startapp``
------------
diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt
index e6162a7fe4..21786d6d63 100644
--- a/docs/releases/2.2.txt
+++ b/docs/releases/2.2.txt
@@ -194,6 +194,10 @@ Management Commands
* On Oracle, :djadmin:`dbshell` is wrapped with ``rlwrap``, if available.
``rlwrap`` provides a command history and editing of keyboard input.
+* The new :option:`makemigrations --no-header` option avoids writing header
+ comments in generated migration file(s). This option is also available for
+ :djadmin:`squashmigrations`.
+
Migrations
~~~~~~~~~~
diff --git a/tests/migrations/test_writer.py b/tests/migrations/test_writer.py
index f7ec6f4bd3..467ff4475b 100644
--- a/tests/migrations/test_writer.py
+++ b/tests/migrations/test_writer.py
@@ -613,16 +613,21 @@ class WriterTests(SimpleTestCase):
})
dt = datetime.datetime(2015, 7, 31, 4, 40, 0, 0, tzinfo=utc)
with mock.patch('django.db.migrations.writer.now', lambda: dt):
- writer = MigrationWriter(migration)
- output = writer.as_string()
+ for include_header in (True, False):
+ with self.subTest(include_header=include_header):
+ writer = MigrationWriter(migration, include_header)
+ output = writer.as_string()
- self.assertTrue(
- output.startswith(
- "# Generated by Django %(version)s on 2015-07-31 04:40\n" % {
- 'version': get_version(),
- }
- )
- )
+ self.assertEqual(
+ include_header,
+ output.startswith(
+ "# Generated by Django %s on 2015-07-31 04:40\n\n" % get_version()
+ )
+ )
+ if not include_header:
+ # Make sure the output starts with something that's not
+ # a comment or indentation or blank line
+ self.assertRegex(output.splitlines(keepends=True)[0], r"^[^#\s]+")
def test_models_import_omitted(self):
"""