Skip to content

Commit

Permalink
Fixed #24098 -- Added no-op attributes to RunPython and RunSQL
Browse files Browse the repository at this point in the history
Thanks Loïc Bistuer and Tim Graham for the discussion and review.
  • Loading branch information
MarkusH authored and timgraham committed Jan 9, 2015
1 parent 67d6a8c commit c8bac4b
Show file tree
Hide file tree
Showing 25 changed files with 72 additions and 26 deletions.
15 changes: 10 additions & 5 deletions django/db/migrations/operations/special.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class RunSQL(Operation):
Also accepts a list of operations that represent the state change effected
by this SQL change, in case it's custom column/table creation/deletion.
"""
noop = ''

def __init__(self, sql, reverse_sql=None, state_operations=None):
self.sql = sql
Expand Down Expand Up @@ -100,9 +101,9 @@ def database_backwards(self, app_label, schema_editor, from_state, to_state):
def describe(self):
return "Raw SQL operation"

def _run_sql(self, schema_editor, sql):
if isinstance(sql, (list, tuple)):
for sql in sql:
def _run_sql(self, schema_editor, sqls):
if isinstance(sqls, (list, tuple)):
for sql in sqls:
params = None
if isinstance(sql, (list, tuple)):
elements = len(sql)
Expand All @@ -111,8 +112,8 @@ def _run_sql(self, schema_editor, sql):
else:
raise ValueError("Expected a 2-tuple but got %d" % elements)
schema_editor.execute(sql, params=params)
else:
statements = schema_editor.connection.ops.prepare_sql_script(sql)
elif sqls != RunSQL.noop:
statements = schema_editor.connection.ops.prepare_sql_script(sqls)
for statement in statements:
schema_editor.execute(statement, params=None)

Expand Down Expand Up @@ -175,3 +176,7 @@ def database_backwards(self, app_label, schema_editor, from_state, to_state):

def describe(self):
return "Raw Python operation"

@staticmethod
def noop(apps, schema_editor):
return None
16 changes: 16 additions & 0 deletions docs/ref/migration-operations.txt
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,14 @@ operation that adds that field and so will try to run it again).
The ability to pass parameters to the ``sql`` and ``reverse_sql`` queries
was added.

.. attribute:: RunSQL.noop

.. versionadded:: 1.8

Pass the ``RunSQL.noop`` attribute to ``sql`` or ``reverse_sql`` when you
want the operation not to do anything in the given direction. This is
especially useful in making the operation reversible.

.. _sqlparse: https://pypi.python.org/pypi/sqlparse

RunPython
Expand Down Expand Up @@ -321,6 +329,14 @@ set ``atomic=False``.
``schema_editor.connection.alias``, where ``schema_editor`` is the second
argument to your function).

.. staticmethod:: RunPython.noop

.. versionadded:: 1.8

Pass the ``RunPython.noop`` method to ``code`` or ``reverse_code`` when
you want the operation not to do anything in the given direction. This is
especially useful in making the operation reversible.

SeparateDatabaseAndState
------------------------

Expand Down
5 changes: 5 additions & 0 deletions docs/releases/1.8.txt
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,11 @@ Migrations
* A :ref:`generic mechanism to handle the deprecation of model fields
<migrations-removing-model-fields>` was added.

* The :attr:`RunPython.noop <django.db.migrations.operations.RunPython.noop>`
and :meth:`RunSQL.noop() <django.db.migrations.operations.RunSQL.noop>` class
attribute/method were added to ease in making ``RunPython`` and ``RunSQL``
operations reversible.

Models
^^^^^^

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
class Migration(migrations.Migration):

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "1_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "2_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "2_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "3_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "4_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "5_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "6_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
class Migration(migrations.Migration):

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto"), ("app2", "2_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "2_auto"), ("app2", "2_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "3_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ class Migration(migrations.Migration):
dependencies = [("app1", "1_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("app2", "1_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
class Migration(migrations.Migration):

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "1_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "2_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "5_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ class Migration(migrations.Migration):
dependencies = [("migrations", "6_auto")]

operations = [
migrations.RunPython(lambda apps, schema_editor: None)
migrations.RunPython(migrations.RunPython.noop)
]
20 changes: 20 additions & 0 deletions tests/migrations/test_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,15 @@ def test_run_sql_params_invalid(self):
operation.database_backwards,
"test_runsql", editor, new_state, project_state)

def test_run_sql_noop(self):
"""
#24098 - Tests no-op RunSQL operations.
"""
operation = migrations.RunSQL(migrations.RunSQL.noop, migrations.RunSQL.noop)
with connection.schema_editor() as editor:
operation.database_forwards("test_runsql", editor, None, None)
operation.database_backwards("test_runsql", editor, None, None)

def test_run_python(self):
"""
Tests the RunPython operation
Expand Down Expand Up @@ -1620,6 +1629,17 @@ def inner_method(models, schema_editor):
self.assertEqual(definition[1], [])
self.assertEqual(sorted(definition[2]), ["atomic", "code"])

def test_run_python_noop(self):
"""
#24098 - Tests no-op RunPython operations.
"""
project_state = ProjectState()
new_state = project_state.clone()
operation = migrations.RunPython(migrations.RunPython.noop, migrations.RunPython.noop)
with connection.schema_editor() as editor:
operation.database_forwards("test_runpython", editor, project_state, new_state)
operation.database_backwards("test_runpython", editor, new_state, project_state)

@unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse")
def test_separate_database_and_state(self):
"""
Expand Down

0 comments on commit c8bac4b

Please sign in to comment.