Fixed #27300 -- Made makemigrations --dry-run output a string (no bytes)
Thanks Markus Holtermann for the report and the review.
This commit is contained in:
parent
e7fa89fb58
commit
979ea95608
|
@ -1,3 +1,4 @@
|
||||||
|
import io
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
@ -222,7 +223,7 @@ class Command(BaseCommand):
|
||||||
# We just do this once per app
|
# We just do this once per app
|
||||||
directory_created[app_label] = True
|
directory_created[app_label] = True
|
||||||
migration_string = writer.as_string()
|
migration_string = writer.as_string()
|
||||||
with open(writer.path, "wb") as fh:
|
with io.open(writer.path, "w", encoding='utf-8') as fh:
|
||||||
fh.write(migration_string)
|
fh.write(migration_string)
|
||||||
elif self.verbosity == 3:
|
elif self.verbosity == 3:
|
||||||
# Alternatively, makemigrations --dry-run --verbosity 3
|
# Alternatively, makemigrations --dry-run --verbosity 3
|
||||||
|
@ -301,7 +302,7 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
if not self.dry_run:
|
if not self.dry_run:
|
||||||
# Write the merge migrations file to the disk
|
# Write the merge migrations file to the disk
|
||||||
with open(writer.path, "wb") as fh:
|
with io.open(writer.path, "w", encoding='utf-8') as fh:
|
||||||
fh.write(writer.as_string())
|
fh.write(writer.as_string())
|
||||||
if self.verbosity > 0:
|
if self.verbosity > 0:
|
||||||
self.stdout.write("\nCreated new merge migration %s" % writer.path)
|
self.stdout.write("\nCreated new merge migration %s" % writer.path)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import io
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
from django.db import DEFAULT_DB_ALIAS, connections, migrations
|
from django.db import DEFAULT_DB_ALIAS, connections, migrations
|
||||||
|
@ -162,7 +164,7 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
# Write out the new migration file
|
# Write out the new migration file
|
||||||
writer = MigrationWriter(new_migration)
|
writer = MigrationWriter(new_migration)
|
||||||
with open(writer.path, "wb") as fh:
|
with io.open(writer.path, "w", encoding='utf-8') as fh:
|
||||||
fh.write(writer.as_string())
|
fh.write(writer.as_string())
|
||||||
|
|
||||||
if self.verbosity > 0:
|
if self.verbosity > 0:
|
||||||
|
|
|
@ -217,7 +217,7 @@ class MigrationWriter(object):
|
||||||
if self.migration.initial:
|
if self.migration.initial:
|
||||||
items['initial_str'] = "\n initial = True\n"
|
items['initial_str'] = "\n initial = True\n"
|
||||||
|
|
||||||
return (MIGRATION_TEMPLATE % items).encode("utf8")
|
return MIGRATION_TEMPLATE % items
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def basedir(self):
|
def basedir(self):
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import codecs
|
|
||||||
import datetime
|
import datetime
|
||||||
import importlib
|
import importlib
|
||||||
|
import io
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -553,7 +553,7 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
initial_file = os.path.join(migration_dir, "0001_initial.py")
|
initial_file = os.path.join(migration_dir, "0001_initial.py")
|
||||||
self.assertTrue(os.path.exists(initial_file))
|
self.assertTrue(os.path.exists(initial_file))
|
||||||
|
|
||||||
with codecs.open(initial_file, 'r', encoding='utf-8') as fp:
|
with io.open(initial_file, 'r', encoding='utf-8') as fp:
|
||||||
content = fp.read()
|
content = fp.read()
|
||||||
self.assertIn('# -*- coding: utf-8 -*-', content)
|
self.assertIn('# -*- coding: utf-8 -*-', content)
|
||||||
self.assertIn('migrations.CreateModel', content)
|
self.assertIn('migrations.CreateModel', content)
|
||||||
|
@ -696,7 +696,7 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
initial_file = os.path.join(migration_dir, "0001_initial.py")
|
initial_file = os.path.join(migration_dir, "0001_initial.py")
|
||||||
self.assertTrue(os.path.exists(initial_file))
|
self.assertTrue(os.path.exists(initial_file))
|
||||||
|
|
||||||
with codecs.open(initial_file, 'r', encoding='utf-8') as fp:
|
with io.open(initial_file, 'r', encoding='utf-8') as fp:
|
||||||
content = fp.read()
|
content = fp.read()
|
||||||
self.assertIn('# -*- coding: utf-8 -*-', content)
|
self.assertIn('# -*- coding: utf-8 -*-', content)
|
||||||
|
|
||||||
|
@ -788,7 +788,7 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
call_command("makemigrations", "migrations", name="merge", merge=True, interactive=True, stdout=out)
|
call_command("makemigrations", "migrations", name="merge", merge=True, interactive=True, stdout=out)
|
||||||
merge_file = os.path.join(migration_dir, '0003_merge.py')
|
merge_file = os.path.join(migration_dir, '0003_merge.py')
|
||||||
self.assertTrue(os.path.exists(merge_file))
|
self.assertTrue(os.path.exists(merge_file))
|
||||||
self.assertIn("Created new merge migration", force_text(out.getvalue()))
|
self.assertIn("Created new merge migration", out.getvalue())
|
||||||
|
|
||||||
@mock.patch('django.db.migrations.utils.datetime')
|
@mock.patch('django.db.migrations.utils.datetime')
|
||||||
def test_makemigrations_default_merge_name(self, mock_datetime):
|
def test_makemigrations_default_merge_name(self, mock_datetime):
|
||||||
|
@ -799,7 +799,7 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
call_command("makemigrations", "migrations", merge=True, interactive=True, stdout=out)
|
call_command("makemigrations", "migrations", merge=True, interactive=True, stdout=out)
|
||||||
merge_file = os.path.join(migration_dir, '0003_merge_20160102_0304.py')
|
merge_file = os.path.join(migration_dir, '0003_merge_20160102_0304.py')
|
||||||
self.assertTrue(os.path.exists(merge_file))
|
self.assertTrue(os.path.exists(merge_file))
|
||||||
self.assertIn("Created new merge migration", force_text(out.getvalue()))
|
self.assertIn("Created new merge migration", out.getvalue())
|
||||||
|
|
||||||
def test_makemigrations_non_interactive_not_null_addition(self):
|
def test_makemigrations_non_interactive_not_null_addition(self):
|
||||||
"""
|
"""
|
||||||
|
@ -832,7 +832,7 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
out = six.StringIO()
|
out = six.StringIO()
|
||||||
with self.temporary_migration_module(module="migrations.test_migrations"):
|
with self.temporary_migration_module(module="migrations.test_migrations"):
|
||||||
call_command("makemigrations", "migrations", interactive=False, stdout=out)
|
call_command("makemigrations", "migrations", interactive=False, stdout=out)
|
||||||
self.assertIn("Alter field slug on author", force_text(out.getvalue()))
|
self.assertIn("Alter field slug on author", out.getvalue())
|
||||||
|
|
||||||
def test_makemigrations_non_interactive_no_model_rename(self):
|
def test_makemigrations_non_interactive_no_model_rename(self):
|
||||||
"""
|
"""
|
||||||
|
@ -847,8 +847,8 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
out = six.StringIO()
|
out = six.StringIO()
|
||||||
with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
|
with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
|
||||||
call_command("makemigrations", "migrations", interactive=False, stdout=out)
|
call_command("makemigrations", "migrations", interactive=False, stdout=out)
|
||||||
self.assertIn("Delete model SillyModel", force_text(out.getvalue()))
|
self.assertIn("Delete model SillyModel", out.getvalue())
|
||||||
self.assertIn("Create model RenamedModel", force_text(out.getvalue()))
|
self.assertIn("Create model RenamedModel", out.getvalue())
|
||||||
|
|
||||||
def test_makemigrations_non_interactive_no_field_rename(self):
|
def test_makemigrations_non_interactive_no_field_rename(self):
|
||||||
"""
|
"""
|
||||||
|
@ -863,8 +863,8 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
out = six.StringIO()
|
out = six.StringIO()
|
||||||
with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
|
with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
|
||||||
call_command("makemigrations", "migrations", interactive=False, stdout=out)
|
call_command("makemigrations", "migrations", interactive=False, stdout=out)
|
||||||
self.assertIn("Remove field silly_field from sillymodel", force_text(out.getvalue()))
|
self.assertIn("Remove field silly_field from sillymodel", out.getvalue())
|
||||||
self.assertIn("Add field silly_rename to sillymodel", force_text(out.getvalue()))
|
self.assertIn("Add field silly_rename to sillymodel", out.getvalue())
|
||||||
|
|
||||||
def test_makemigrations_handle_merge(self):
|
def test_makemigrations_handle_merge(self):
|
||||||
"""
|
"""
|
||||||
|
@ -875,7 +875,7 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
call_command("makemigrations", "migrations", name="merge", merge=True, interactive=False, stdout=out)
|
call_command("makemigrations", "migrations", name="merge", merge=True, interactive=False, stdout=out)
|
||||||
merge_file = os.path.join(migration_dir, '0003_merge.py')
|
merge_file = os.path.join(migration_dir, '0003_merge.py')
|
||||||
self.assertTrue(os.path.exists(merge_file))
|
self.assertTrue(os.path.exists(merge_file))
|
||||||
output = force_text(out.getvalue())
|
output = out.getvalue()
|
||||||
self.assertIn("Merging migrations", output)
|
self.assertIn("Merging migrations", output)
|
||||||
self.assertIn("Branch 0002_second", output)
|
self.assertIn("Branch 0002_second", output)
|
||||||
self.assertIn("Branch 0002_conflicting_second", output)
|
self.assertIn("Branch 0002_conflicting_second", output)
|
||||||
|
@ -894,7 +894,7 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
)
|
)
|
||||||
merge_file = os.path.join(migration_dir, '0003_merge.py')
|
merge_file = os.path.join(migration_dir, '0003_merge.py')
|
||||||
self.assertFalse(os.path.exists(merge_file))
|
self.assertFalse(os.path.exists(merge_file))
|
||||||
output = force_text(out.getvalue())
|
output = out.getvalue()
|
||||||
self.assertIn("Merging migrations", output)
|
self.assertIn("Merging migrations", output)
|
||||||
self.assertIn("Branch 0002_second", output)
|
self.assertIn("Branch 0002_second", output)
|
||||||
self.assertIn("Branch 0002_conflicting_second", output)
|
self.assertIn("Branch 0002_conflicting_second", output)
|
||||||
|
@ -913,7 +913,7 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
)
|
)
|
||||||
merge_file = os.path.join(migration_dir, '0003_merge.py')
|
merge_file = os.path.join(migration_dir, '0003_merge.py')
|
||||||
self.assertFalse(os.path.exists(merge_file))
|
self.assertFalse(os.path.exists(merge_file))
|
||||||
output = force_text(out.getvalue())
|
output = out.getvalue()
|
||||||
self.assertIn("Merging migrations", output)
|
self.assertIn("Merging migrations", output)
|
||||||
self.assertIn("Branch 0002_second", output)
|
self.assertIn("Branch 0002_second", output)
|
||||||
self.assertIn("Branch 0002_conflicting_second", output)
|
self.assertIn("Branch 0002_conflicting_second", output)
|
||||||
|
@ -921,7 +921,8 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
|
|
||||||
# Additional output caused by verbosity 3
|
# Additional output caused by verbosity 3
|
||||||
# The complete merge migration file that would be written
|
# The complete merge migration file that would be written
|
||||||
self.assertIn("# -*- coding: utf-8 -*-", output)
|
# '\n#' is to verify no bytestring prefix before #
|
||||||
|
self.assertIn("\n# -*- coding: utf-8 -*-", output)
|
||||||
self.assertIn("class Migration(migrations.Migration):", output)
|
self.assertIn("class Migration(migrations.Migration):", output)
|
||||||
self.assertIn("dependencies = [", output)
|
self.assertIn("dependencies = [", output)
|
||||||
self.assertIn("('migrations', '0002_second')", output)
|
self.assertIn("('migrations', '0002_second')", output)
|
||||||
|
@ -1092,7 +1093,7 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
migration_file = os.path.join(migration_dir, "%s_%s.py" % (migration_count, migration_name))
|
migration_file = os.path.join(migration_dir, "%s_%s.py" % (migration_count, migration_name))
|
||||||
# Check for existing migration file in migration folder
|
# Check for existing migration file in migration folder
|
||||||
self.assertTrue(os.path.exists(migration_file))
|
self.assertTrue(os.path.exists(migration_file))
|
||||||
with codecs.open(migration_file, "r", encoding="utf-8") as fp:
|
with io.open(migration_file, "r", encoding="utf-8") as fp:
|
||||||
content = fp.read()
|
content = fp.read()
|
||||||
self.assertIn("# -*- coding: utf-8 -*-", content)
|
self.assertIn("# -*- coding: utf-8 -*-", content)
|
||||||
content = content.replace(" ", "")
|
content = content.replace(" ", "")
|
||||||
|
@ -1182,8 +1183,8 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
out = six.StringIO()
|
out = six.StringIO()
|
||||||
with self.temporary_migration_module(module='migrations.test_auto_now_add'):
|
with self.temporary_migration_module(module='migrations.test_auto_now_add'):
|
||||||
call_command('makemigrations', 'migrations', interactive=True, stdout=out)
|
call_command('makemigrations', 'migrations', interactive=True, stdout=out)
|
||||||
output = force_text(out.getvalue())
|
output = out.getvalue()
|
||||||
prompt_output = force_text(prompt_stdout.getvalue())
|
prompt_output = prompt_stdout.getvalue()
|
||||||
self.assertIn("You can accept the default 'timezone.now' by pressing 'Enter'", prompt_output)
|
self.assertIn("You can accept the default 'timezone.now' by pressing 'Enter'", prompt_output)
|
||||||
self.assertIn("Add field creation_date to entry", output)
|
self.assertIn("Add field creation_date to entry", output)
|
||||||
|
|
||||||
|
@ -1208,7 +1209,7 @@ class SquashMigrationsTests(MigrationTestBase):
|
||||||
call_command("squashmigrations", "migrations", "0002", interactive=False, verbosity=0)
|
call_command("squashmigrations", "migrations", "0002", interactive=False, verbosity=0)
|
||||||
|
|
||||||
squashed_migration_file = os.path.join(migration_dir, "0001_squashed_0002_second.py")
|
squashed_migration_file = os.path.join(migration_dir, "0001_squashed_0002_second.py")
|
||||||
with codecs.open(squashed_migration_file, "r", encoding="utf-8") as fp:
|
with io.open(squashed_migration_file, "r", encoding="utf-8") as fp:
|
||||||
content = fp.read()
|
content = fp.read()
|
||||||
self.assertIn("initial = True", content)
|
self.assertIn("initial = True", content)
|
||||||
|
|
||||||
|
@ -1219,7 +1220,7 @@ class SquashMigrationsTests(MigrationTestBase):
|
||||||
out = six.StringIO()
|
out = six.StringIO()
|
||||||
with self.temporary_migration_module(module="migrations.test_migrations"):
|
with self.temporary_migration_module(module="migrations.test_migrations"):
|
||||||
call_command("squashmigrations", "migrations", "0002", interactive=False, verbosity=1, stdout=out)
|
call_command("squashmigrations", "migrations", "0002", interactive=False, verbosity=1, stdout=out)
|
||||||
self.assertIn("Optimized from 8 operations to 3 operations.", force_text(out.getvalue()))
|
self.assertIn("Optimized from 8 operations to 3 operations.", out.getvalue())
|
||||||
|
|
||||||
def test_ticket_23799_squashmigrations_no_optimize(self):
|
def test_ticket_23799_squashmigrations_no_optimize(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1229,7 +1230,7 @@ class SquashMigrationsTests(MigrationTestBase):
|
||||||
with self.temporary_migration_module(module="migrations.test_migrations"):
|
with self.temporary_migration_module(module="migrations.test_migrations"):
|
||||||
call_command("squashmigrations", "migrations", "0002",
|
call_command("squashmigrations", "migrations", "0002",
|
||||||
interactive=False, verbosity=1, no_optimize=True, stdout=out)
|
interactive=False, verbosity=1, no_optimize=True, stdout=out)
|
||||||
self.assertIn("Skipping optimization", force_text(out.getvalue()))
|
self.assertIn("Skipping optimization", out.getvalue())
|
||||||
|
|
||||||
def test_squashmigrations_valid_start(self):
|
def test_squashmigrations_valid_start(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1241,11 +1242,11 @@ class SquashMigrationsTests(MigrationTestBase):
|
||||||
interactive=False, verbosity=1, stdout=out)
|
interactive=False, verbosity=1, stdout=out)
|
||||||
|
|
||||||
squashed_migration_file = os.path.join(migration_dir, "0002_second_squashed_0003_third.py")
|
squashed_migration_file = os.path.join(migration_dir, "0002_second_squashed_0003_third.py")
|
||||||
with codecs.open(squashed_migration_file, "r", encoding="utf-8") as fp:
|
with io.open(squashed_migration_file, "r", encoding="utf-8") as fp:
|
||||||
content = fp.read()
|
content = fp.read()
|
||||||
self.assertIn(" ('migrations', '0001_initial')", content)
|
self.assertIn(" ('migrations', '0001_initial')", content)
|
||||||
self.assertNotIn("initial = True", content)
|
self.assertNotIn("initial = True", content)
|
||||||
out = force_text(out.getvalue())
|
out = out.getvalue()
|
||||||
self.assertNotIn(" - 0001_initial", out)
|
self.assertNotIn(" - 0001_initial", out)
|
||||||
self.assertIn(" - 0002_second", out)
|
self.assertIn(" - 0002_second", out)
|
||||||
self.assertIn(" - 0003_third", out)
|
self.assertIn(" - 0003_third", out)
|
||||||
|
|
|
@ -25,6 +25,7 @@ from django.test import SimpleTestCase, ignore_warnings, mock
|
||||||
from django.utils import datetime_safe, six
|
from django.utils import datetime_safe, six
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.deconstruct import deconstructible
|
from django.utils.deconstruct import deconstructible
|
||||||
|
from django.utils.encoding import force_str
|
||||||
from django.utils.functional import SimpleLazyObject
|
from django.utils.functional import SimpleLazyObject
|
||||||
from django.utils.timezone import FixedOffset, get_default_timezone, utc
|
from django.utils.timezone import FixedOffset, get_default_timezone, utc
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
@ -181,7 +182,7 @@ class WriterTests(SimpleTestCase):
|
||||||
def safe_exec(self, string, value=None):
|
def safe_exec(self, string, value=None):
|
||||||
l = {}
|
l = {}
|
||||||
try:
|
try:
|
||||||
exec(string, globals(), l)
|
exec(force_str(string), globals(), l)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if value:
|
if value:
|
||||||
self.fail("Could not exec %r (from value %r): %s" % (string.strip(), value, e))
|
self.fail("Could not exec %r (from value %r): %s" % (string.strip(), value, e))
|
||||||
|
@ -546,8 +547,6 @@ class WriterTests(SimpleTestCase):
|
||||||
})
|
})
|
||||||
writer = MigrationWriter(migration)
|
writer = MigrationWriter(migration)
|
||||||
output = writer.as_string()
|
output = writer.as_string()
|
||||||
# It should NOT be unicode.
|
|
||||||
self.assertIsInstance(output, six.binary_type, "Migration as_string returned unicode")
|
|
||||||
# We don't test the output formatting - that's too fragile.
|
# We don't test the output formatting - that's too fragile.
|
||||||
# Just make sure it runs for now, and that things look alright.
|
# Just make sure it runs for now, and that things look alright.
|
||||||
result = self.safe_exec(output)
|
result = self.safe_exec(output)
|
||||||
|
@ -615,7 +614,7 @@ class WriterTests(SimpleTestCase):
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
writer = MigrationWriter(migration)
|
writer = MigrationWriter(migration)
|
||||||
output = writer.as_string().decode('utf-8')
|
output = writer.as_string()
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"import datetime\n"
|
"import datetime\n"
|
||||||
"from django.db import migrations, models\n"
|
"from django.db import migrations, models\n"
|
||||||
|
@ -633,7 +632,7 @@ class WriterTests(SimpleTestCase):
|
||||||
dt = datetime.datetime(2015, 7, 31, 4, 40, 0, 0, tzinfo=utc)
|
dt = datetime.datetime(2015, 7, 31, 4, 40, 0, 0, tzinfo=utc)
|
||||||
with mock.patch('django.db.migrations.writer.now', lambda: dt):
|
with mock.patch('django.db.migrations.writer.now', lambda: dt):
|
||||||
writer = MigrationWriter(migration)
|
writer = MigrationWriter(migration)
|
||||||
output = writer.as_string().decode('utf-8')
|
output = writer.as_string()
|
||||||
|
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
output.startswith(
|
output.startswith(
|
||||||
|
@ -657,7 +656,7 @@ class WriterTests(SimpleTestCase):
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
writer = MigrationWriter(migration)
|
writer = MigrationWriter(migration)
|
||||||
output = writer.as_string().decode('utf-8')
|
output = writer.as_string()
|
||||||
self.assertIn("from django.db import migrations\n", output)
|
self.assertIn("from django.db import migrations\n", output)
|
||||||
|
|
||||||
def test_deconstruct_class_arguments(self):
|
def test_deconstruct_class_arguments(self):
|
||||||
|
|
Loading…
Reference in New Issue