[3.0.x] Fixed #30870 -- Fixed showing that RunPython operations are irreversible by migrate --plan.
Thanks Hasan Ramezani for the initial patch and Kyle Dickerson for the
report.
Backport of 06d34aab7c
from master
This commit is contained in:
parent
4a263af64e
commit
4a756cbc38
|
@ -343,21 +343,21 @@ class Command(BaseCommand):
|
||||||
def describe_operation(operation, backwards):
|
def describe_operation(operation, backwards):
|
||||||
"""Return a string that describes a migration operation for --plan."""
|
"""Return a string that describes a migration operation for --plan."""
|
||||||
prefix = ''
|
prefix = ''
|
||||||
|
is_error = False
|
||||||
if hasattr(operation, 'code'):
|
if hasattr(operation, 'code'):
|
||||||
code = operation.reverse_code if backwards else operation.code
|
code = operation.reverse_code if backwards else operation.code
|
||||||
action = code.__doc__ if code else ''
|
action = (code.__doc__ or '') if code else None
|
||||||
elif hasattr(operation, 'sql'):
|
elif hasattr(operation, 'sql'):
|
||||||
action = operation.reverse_sql if backwards else operation.sql
|
action = operation.reverse_sql if backwards else operation.sql
|
||||||
else:
|
else:
|
||||||
action = ''
|
action = ''
|
||||||
if backwards:
|
if backwards:
|
||||||
prefix = 'Undo '
|
prefix = 'Undo '
|
||||||
if action is None:
|
if action is not None:
|
||||||
|
action = str(action).replace('\n', '')
|
||||||
|
elif backwards:
|
||||||
action = 'IRREVERSIBLE'
|
action = 'IRREVERSIBLE'
|
||||||
is_error = True
|
is_error = True
|
||||||
else:
|
|
||||||
action = str(action).replace('\n', '')
|
|
||||||
is_error = False
|
|
||||||
if action:
|
if action:
|
||||||
action = ' -> ' + action
|
action = ' -> ' + action
|
||||||
truncated = Truncator(action)
|
truncated = Truncator(action)
|
||||||
|
|
|
@ -13,3 +13,7 @@ Bugfixes
|
||||||
``has_keys``, or ``has_any_keys`` lookup on
|
``has_keys``, or ``has_any_keys`` lookup on
|
||||||
:class:`~django.contrib.postgres.fields.JSONField`, if the right or left hand
|
:class:`~django.contrib.postgres.fields.JSONField`, if the right or left hand
|
||||||
side of an expression is a key transform (:ticket:`30826`).
|
side of an expression is a key transform (:ticket:`30826`).
|
||||||
|
|
||||||
|
* Prevented :option:`migrate --plan` from showing that ``RunPython`` operations
|
||||||
|
are irreversible when ``reverse_code`` callables don't have docstrings or
|
||||||
|
when showing a forward migration plan (:ticket:`30870`).
|
||||||
|
|
|
@ -371,6 +371,28 @@ class MigrateTests(MigrationTestBase):
|
||||||
' Raw SQL operation -> IRREVERSIBLE\n',
|
' Raw SQL operation -> IRREVERSIBLE\n',
|
||||||
out.getvalue()
|
out.getvalue()
|
||||||
)
|
)
|
||||||
|
out = io.StringIO()
|
||||||
|
call_command('migrate', 'migrations', '0005', plan=True, stdout=out, no_color=True)
|
||||||
|
# Operation is marked as irreversible only in the revert plan.
|
||||||
|
self.assertEqual(
|
||||||
|
'Planned operations:\n'
|
||||||
|
'migrations.0005_fifth\n'
|
||||||
|
' Raw Python operation\n'
|
||||||
|
' Raw Python operation\n'
|
||||||
|
' Raw Python operation -> Feed salamander.\n',
|
||||||
|
out.getvalue()
|
||||||
|
)
|
||||||
|
call_command('migrate', 'migrations', '0005', verbosity=0)
|
||||||
|
out = io.StringIO()
|
||||||
|
call_command('migrate', 'migrations', '0004', plan=True, stdout=out, no_color=True)
|
||||||
|
self.assertEqual(
|
||||||
|
'Planned operations:\n'
|
||||||
|
'migrations.0005_fifth\n'
|
||||||
|
' Raw Python operation -> IRREVERSIBLE\n'
|
||||||
|
' Raw Python operation -> IRREVERSIBLE\n'
|
||||||
|
' Raw Python operation\n',
|
||||||
|
out.getvalue()
|
||||||
|
)
|
||||||
finally:
|
finally:
|
||||||
# Cleanup by unmigrating everything: fake the irreversible, then
|
# Cleanup by unmigrating everything: fake the irreversible, then
|
||||||
# migrate all to zero.
|
# migrate all to zero.
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def grow_tail(x, y):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def feed(x, y):
|
||||||
|
"""Feed salamander."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
('migrations', '0004_fourth'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(migrations.RunPython.noop),
|
||||||
|
migrations.RunPython(grow_tail),
|
||||||
|
migrations.RunPython(feed, migrations.RunPython.noop),
|
||||||
|
]
|
Loading…
Reference in New Issue