mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	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.
This commit is contained in:
		| @@ -343,21 +343,21 @@ class Command(BaseCommand): | ||||
|     def describe_operation(operation, backwards): | ||||
|         """Return a string that describes a migration operation for --plan.""" | ||||
|         prefix = '' | ||||
|         is_error = False | ||||
|         if hasattr(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'): | ||||
|             action = operation.reverse_sql if backwards else operation.sql | ||||
|         else: | ||||
|             action = '' | ||||
|             if backwards: | ||||
|                 prefix = 'Undo ' | ||||
|         if action is None: | ||||
|         if action is not None: | ||||
|             action = str(action).replace('\n', '') | ||||
|         elif backwards: | ||||
|             action = 'IRREVERSIBLE' | ||||
|             is_error = True | ||||
|         else: | ||||
|             action = str(action).replace('\n', '') | ||||
|             is_error = False | ||||
|         if action: | ||||
|             action = ' -> ' + action | ||||
|         truncated = Truncator(action) | ||||
|   | ||||
| @@ -13,3 +13,7 @@ Bugfixes | ||||
|   ``has_keys``, or ``has_any_keys`` lookup on | ||||
|   :class:`~django.contrib.postgres.fields.JSONField`, if the right or left hand | ||||
|   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', | ||||
|                 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: | ||||
|             # Cleanup by unmigrating everything: fake the irreversible, then | ||||
|             # migrate all to zero. | ||||
|   | ||||
							
								
								
									
										22
									
								
								tests/migrations/test_migrations_plan/0005_fifth.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								tests/migrations/test_migrations_plan/0005_fifth.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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), | ||||
|     ] | ||||
		Reference in New Issue
	
	Block a user