[1.8.x] Fixed #24278 -- Fixed serialization of migration operations.

Fixed MigrationWriter.serialize() to correctly handle migration
operations by utilizing OperationWriter.

Thanks Piotr Maliński for the report.

Backport of e8e4f978dd from master
This commit is contained in:
Marten Kenbeek 2015-04-05 15:59:23 +02:00 committed by Markus Holtermann
parent 651cc369ad
commit 773387ce42
4 changed files with 54 additions and 0 deletions

View File

@ -437,6 +437,7 @@ answer newbie questions, and generally made Django that much better:
Mark Lavin <markdlavin@gmail.com>
Mark Sandstrom <mark@deliciouslynerdy.com>
Markus Holtermann <https://markusholtermann.eu>
Marten Kenbeek <marten.knbk+django@gmail.com>
martin.glueck@gmail.com
Martin Green
Martin Kosír <martin@martinkosir.net>

View File

@ -14,6 +14,7 @@ from importlib import import_module
from django.apps import apps
from django.db import migrations, models
from django.db.migrations.loader import MigrationLoader
from django.db.migrations.operations.base import Operation
from django.utils import datetime_safe, six
from django.utils._os import upath
from django.utils.encoding import force_text
@ -395,6 +396,10 @@ class MigrationWriter(object):
return "%s.as_manager()" % name, imports
else:
return cls.serialize_deconstructed(manager_path, args, kwargs)
elif isinstance(value, Operation):
string, imports = OperationWriter(value, indentation=0).serialize()
# Nested operation, trailing comma is handled in upper OperationWriter._write()
return string.rstrip(','), imports
# Anything that knows how to deconstruct itself.
elif hasattr(value, 'deconstruct'):
return cls.serialize_deconstructed(*value.deconstruct())

View File

@ -17,3 +17,7 @@ Bugfixes
* Prevented ``TypeError`` in translation functions ``check_for_language()`` and
``get_language_bidi()`` when translations are deactivated (:ticket:`24569`).
* Fixed :djadmin:`squashmigrations` command when using
:class:`~django.db.migrations.operations.SeparateDatabaseAndState`
(:ticket:`24278`).

View File

@ -81,6 +81,27 @@ class OperationWriterTests(SimpleTestCase):
'),'
)
def test_nested_args_signature(self):
operation = custom_migration_operations.operations.ArgsOperation(
custom_migration_operations.operations.ArgsOperation(1, 2),
custom_migration_operations.operations.KwargsOperation(kwarg1=3, kwarg2=4)
)
buff, imports = OperationWriter(operation, indentation=0).serialize()
self.assertEqual(imports, {'import custom_migration_operations.operations'})
self.assertEqual(
buff,
'custom_migration_operations.operations.ArgsOperation(\n'
' arg1=custom_migration_operations.operations.ArgsOperation(\n'
' arg1=1,\n'
' arg2=2,\n'
' ),\n'
' arg2=custom_migration_operations.operations.KwargsOperation(\n'
' kwarg1=3,\n'
' kwarg2=4,\n'
' ),\n'
'),'
)
def test_multiline_args_signature(self):
operation = custom_migration_operations.operations.ArgsOperation("test\n arg1", "test\narg2")
buff, imports = OperationWriter(operation, indentation=0).serialize()
@ -107,6 +128,29 @@ class OperationWriterTests(SimpleTestCase):
'),'
)
def test_nested_operation_expand_args_signature(self):
operation = custom_migration_operations.operations.ExpandArgsOperation(
arg=[
custom_migration_operations.operations.KwargsOperation(
kwarg1=1,
kwarg2=2,
),
]
)
buff, imports = OperationWriter(operation, indentation=0).serialize()
self.assertEqual(imports, {'import custom_migration_operations.operations'})
self.assertEqual(
buff,
'custom_migration_operations.operations.ExpandArgsOperation(\n'
' arg=[\n'
' custom_migration_operations.operations.KwargsOperation(\n'
' kwarg1=1,\n'
' kwarg2=2,\n'
' ),\n'
' ],\n'
'),'
)
class WriterTests(TestCase):
"""