Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Made MigrationWriter look for a "deconstruct" attribute on functions.

Refs #20978.
  • Loading branch information...
commit d59f1993f150f83524051d96b52df08da4dcf011 1 parent 5df8f74
@loic loic authored timgraham committed
View
40 django/db/migrations/writer.py
@@ -74,6 +74,26 @@ def path(self):
return os.path.join(basedir, self.filename)
@classmethod
+ def serialize_deconstructed(cls, path, args, kwargs):
+ module, name = path.rsplit(".", 1)
+ if module == "django.db.models":
+ imports = set(["from django.db import models"])
+ name = "models.%s" % name
+ else:
+ imports = set(["import %s" % module])
+ name = path
+ arg_strings = []
+ for arg in args:
+ arg_string, arg_imports = cls.serialize(arg)
+ arg_strings.append(arg_string)
+ imports.update(arg_imports)
+ for kw, arg in kwargs.items():
+ arg_string, arg_imports = cls.serialize(arg)
+ imports.update(arg_imports)
+ arg_strings.append("%s=%s" % (kw, arg_string))
+ return "%s(%s)" % (name, ", ".join(arg_strings)), imports
+
+ @classmethod
def serialize(cls, value):
"""
Serializes the value to a string that's parsable by Python, along
@@ -119,23 +139,7 @@ def serialize(cls, value):
# Django fields
elif isinstance(value, models.Field):
attr_name, path, args, kwargs = value.deconstruct()
- module, name = path.rsplit(".", 1)
- if module == "django.db.models":
- imports = set(["from django.db import models"])
- name = "models.%s" % name
- else:
- imports = set(["import %s" % module])
- name = path
- arg_strings = []
- for arg in args:
- arg_string, arg_imports = cls.serialize(arg)
- arg_strings.append(arg_string)
- imports.update(arg_imports)
- for kw, arg in kwargs.items():
- arg_string, arg_imports = cls.serialize(arg)
- imports.update(arg_imports)
- arg_strings.append("%s=%s" % (kw, arg_string))
- return "%s(%s)" % (name, ", ".join(arg_strings)), imports
+ return cls.serialize_deconstructed(path, args, kwargs)
# Functions
elif isinstance(value, (types.FunctionType, types.BuiltinFunctionType)):
# Special-cases, as these don't have im_class
@@ -152,6 +156,8 @@ def serialize(cls, value):
klass = value.im_class
module = klass.__module__
return "%s.%s.%s" % (module, klass.__name__, value.__name__), set(["import %s" % module])
+ elif hasattr(value, 'deconstruct'):
+ return cls.serialize_deconstructed(*value.deconstruct())
elif value.__name__ == '<lambda>':
raise ValueError("Cannot serialize function: lambda")
elif value.__module__ is None:
View
1  django/db/models/deletion.py
@@ -35,6 +35,7 @@ def set_on_delete(collector, field, sub_objs, using):
else:
def set_on_delete(collector, field, sub_objs, using):
collector.add_field_update(field, value, sub_objs)
+ set_on_delete.deconstruct = lambda: ('django.db.models.SET', (value,), {})
return set_on_delete
View
4 tests/migrations/test_writer.py
@@ -63,6 +63,10 @@ def test_serialize(self):
# Functions
with six.assertRaisesRegex(self, ValueError, 'Cannot serialize function: lambda'):
self.assertSerializedEqual(lambda x: 42)
+ self.assertSerializedEqual(models.SET_NULL)
+ string, imports = MigrationWriter.serialize(models.SET(42))
+ self.assertEqual(string, 'models.SET(42)')
+ self.serialize_round_trip(models.SET(42))
# Datetime stuff
self.assertSerializedEqual(datetime.datetime.utcnow())
self.assertSerializedEqual(datetime.datetime.utcnow)
Please sign in to comment.
Something went wrong with that request. Please try again.