mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #34697 -- Fixed non-deterministic order of dependencies and sets/frozensets in migrations.
Co-authored-by: Dakota Hawkins <dakotahawkins@gmail.com>
This commit is contained in:
parent
4afaeb14c2
commit
02966a30dd
1
AUTHORS
1
AUTHORS
@ -1043,6 +1043,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
ye7cakf02@sneakemail.com
|
ye7cakf02@sneakemail.com
|
||||||
ymasuda@ethercube.com
|
ymasuda@ethercube.com
|
||||||
Yoong Kang Lim <yoongkang.lim@gmail.com>
|
Yoong Kang Lim <yoongkang.lim@gmail.com>
|
||||||
|
Yury V. Zaytsev <yury@shurup.com>
|
||||||
Yusuke Miyazaki <miyazaki.dev@gmail.com>
|
Yusuke Miyazaki <miyazaki.dev@gmail.com>
|
||||||
yyyyyyyan <contact@yyyyyyyan.tech>
|
yyyyyyyan <contact@yyyyyyyan.tech>
|
||||||
Zac Hatfield-Dodds <zac.hatfield.dodds@gmail.com>
|
Zac Hatfield-Dodds <zac.hatfield.dodds@gmail.com>
|
||||||
|
@ -46,6 +46,11 @@ class BaseSequenceSerializer(BaseSerializer):
|
|||||||
return value % (", ".join(strings)), imports
|
return value % (", ".join(strings)), imports
|
||||||
|
|
||||||
|
|
||||||
|
class BaseUnorderedSequenceSerializer(BaseSequenceSerializer):
|
||||||
|
def __init__(self, value):
|
||||||
|
super().__init__(sorted(value, key=repr))
|
||||||
|
|
||||||
|
|
||||||
class BaseSimpleSerializer(BaseSerializer):
|
class BaseSimpleSerializer(BaseSerializer):
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
return repr(self.value), set()
|
return repr(self.value), set()
|
||||||
@ -151,7 +156,7 @@ class FloatSerializer(BaseSimpleSerializer):
|
|||||||
return super().serialize()
|
return super().serialize()
|
||||||
|
|
||||||
|
|
||||||
class FrozensetSerializer(BaseSequenceSerializer):
|
class FrozensetSerializer(BaseUnorderedSequenceSerializer):
|
||||||
def _format(self):
|
def _format(self):
|
||||||
return "frozenset([%s])"
|
return "frozenset([%s])"
|
||||||
|
|
||||||
@ -279,7 +284,7 @@ class SequenceSerializer(BaseSequenceSerializer):
|
|||||||
return "[%s]"
|
return "[%s]"
|
||||||
|
|
||||||
|
|
||||||
class SetSerializer(BaseSequenceSerializer):
|
class SetSerializer(BaseUnorderedSequenceSerializer):
|
||||||
def _format(self):
|
def _format(self):
|
||||||
# Serialize as a set literal except when value is empty because {}
|
# Serialize as a set literal except when value is empty because {}
|
||||||
# is an empty dict.
|
# is an empty dict.
|
||||||
|
@ -154,7 +154,9 @@ class MigrationWriter:
|
|||||||
imports.add("from django.conf import settings")
|
imports.add("from django.conf import settings")
|
||||||
else:
|
else:
|
||||||
dependencies.append(" %s," % self.serialize(dependency)[0])
|
dependencies.append(" %s," % self.serialize(dependency)[0])
|
||||||
items["dependencies"] = "\n".join(dependencies) + "\n" if dependencies else ""
|
items["dependencies"] = (
|
||||||
|
"\n".join(sorted(dependencies)) + "\n" if dependencies else ""
|
||||||
|
)
|
||||||
|
|
||||||
# Format imports nicely, swapping imports of functions from migration files
|
# Format imports nicely, swapping imports of functions from migration files
|
||||||
# for comments
|
# for comments
|
||||||
|
@ -768,12 +768,17 @@ class WriterTests(SimpleTestCase):
|
|||||||
def test_serialize_frozensets(self):
|
def test_serialize_frozensets(self):
|
||||||
self.assertSerializedEqual(frozenset())
|
self.assertSerializedEqual(frozenset())
|
||||||
self.assertSerializedEqual(frozenset("let it go"))
|
self.assertSerializedEqual(frozenset("let it go"))
|
||||||
|
self.assertSerializedResultEqual(
|
||||||
|
frozenset("cba"), ("frozenset(['a', 'b', 'c'])", set())
|
||||||
|
)
|
||||||
|
|
||||||
def test_serialize_set(self):
|
def test_serialize_set(self):
|
||||||
self.assertSerializedEqual(set())
|
self.assertSerializedEqual(set())
|
||||||
self.assertSerializedResultEqual(set(), ("set()", set()))
|
self.assertSerializedResultEqual(set(), ("set()", set()))
|
||||||
self.assertSerializedEqual({"a"})
|
self.assertSerializedEqual({"a"})
|
||||||
self.assertSerializedResultEqual({"a"}, ("{'a'}", set()))
|
self.assertSerializedResultEqual({"a"}, ("{'a'}", set()))
|
||||||
|
self.assertSerializedEqual({"c", "b", "a"})
|
||||||
|
self.assertSerializedResultEqual({"c", "b", "a"}, ("{'a', 'b', 'c'}", set()))
|
||||||
|
|
||||||
def test_serialize_timedelta(self):
|
def test_serialize_timedelta(self):
|
||||||
self.assertSerializedEqual(datetime.timedelta())
|
self.assertSerializedEqual(datetime.timedelta())
|
||||||
@ -891,6 +896,33 @@ class WriterTests(SimpleTestCase):
|
|||||||
result["custom_migration_operations"].more_operations.TestOperation,
|
result["custom_migration_operations"].more_operations.TestOperation,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_sorted_dependencies(self):
|
||||||
|
migration = type(
|
||||||
|
"Migration",
|
||||||
|
(migrations.Migration,),
|
||||||
|
{
|
||||||
|
"operations": [
|
||||||
|
migrations.AddField("mymodel", "myfield", models.IntegerField()),
|
||||||
|
],
|
||||||
|
"dependencies": [
|
||||||
|
("testapp10", "0005_fifth"),
|
||||||
|
("testapp02", "0005_third"),
|
||||||
|
("testapp02", "0004_sixth"),
|
||||||
|
("testapp01", "0001_initial"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
output = MigrationWriter(migration, include_header=False).as_string()
|
||||||
|
self.assertIn(
|
||||||
|
" dependencies = [\n"
|
||||||
|
" ('testapp01', '0001_initial'),\n"
|
||||||
|
" ('testapp02', '0004_sixth'),\n"
|
||||||
|
" ('testapp02', '0005_third'),\n"
|
||||||
|
" ('testapp10', '0005_fifth'),\n"
|
||||||
|
" ]",
|
||||||
|
output,
|
||||||
|
)
|
||||||
|
|
||||||
def test_sorted_imports(self):
|
def test_sorted_imports(self):
|
||||||
"""
|
"""
|
||||||
#24155 - Tests ordering of imports.
|
#24155 - Tests ordering of imports.
|
||||||
|
Loading…
Reference in New Issue
Block a user