Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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

Refs #20978.
  • Loading branch information...
commit d59f1993f150f83524051d96b52df08da4dcf011 1 parent 5df8f74
Loic Bistuer authored timgraham committed
40  django/db/migrations/writer.py
@@ -74,6 +74,26 @@ def path(self):
74 74
         return os.path.join(basedir, self.filename)
75 75
 
76 76
     @classmethod
  77
+    def serialize_deconstructed(cls, path, args, kwargs):
  78
+        module, name = path.rsplit(".", 1)
  79
+        if module == "django.db.models":
  80
+            imports = set(["from django.db import models"])
  81
+            name = "models.%s" % name
  82
+        else:
  83
+            imports = set(["import %s" % module])
  84
+            name = path
  85
+        arg_strings = []
  86
+        for arg in args:
  87
+            arg_string, arg_imports = cls.serialize(arg)
  88
+            arg_strings.append(arg_string)
  89
+            imports.update(arg_imports)
  90
+        for kw, arg in kwargs.items():
  91
+            arg_string, arg_imports = cls.serialize(arg)
  92
+            imports.update(arg_imports)
  93
+            arg_strings.append("%s=%s" % (kw, arg_string))
  94
+        return "%s(%s)" % (name, ", ".join(arg_strings)), imports
  95
+
  96
+    @classmethod
77 97
     def serialize(cls, value):
78 98
         """
79 99
         Serializes the value to a string that's parsable by Python, along
@@ -119,23 +139,7 @@ def serialize(cls, value):
119 139
         # Django fields
120 140
         elif isinstance(value, models.Field):
121 141
             attr_name, path, args, kwargs = value.deconstruct()
122  
-            module, name = path.rsplit(".", 1)
123  
-            if module == "django.db.models":
124  
-                imports = set(["from django.db import models"])
125  
-                name = "models.%s" % name
126  
-            else:
127  
-                imports = set(["import %s" % module])
128  
-                name = path
129  
-            arg_strings = []
130  
-            for arg in args:
131  
-                arg_string, arg_imports = cls.serialize(arg)
132  
-                arg_strings.append(arg_string)
133  
-                imports.update(arg_imports)
134  
-            for kw, arg in kwargs.items():
135  
-                arg_string, arg_imports = cls.serialize(arg)
136  
-                imports.update(arg_imports)
137  
-                arg_strings.append("%s=%s" % (kw, arg_string))
138  
-            return "%s(%s)" % (name, ", ".join(arg_strings)), imports
  142
+            return cls.serialize_deconstructed(path, args, kwargs)
139 143
         # Functions
140 144
         elif isinstance(value, (types.FunctionType, types.BuiltinFunctionType)):
141 145
             # Special-cases, as these don't have im_class
@@ -152,6 +156,8 @@ def serialize(cls, value):
152 156
                 klass = value.im_class
153 157
                 module = klass.__module__
154 158
                 return "%s.%s.%s" % (module, klass.__name__, value.__name__), set(["import %s" % module])
  159
+            elif hasattr(value, 'deconstruct'):
  160
+                return cls.serialize_deconstructed(*value.deconstruct())
155 161
             elif value.__name__ == '<lambda>':
156 162
                 raise ValueError("Cannot serialize function: lambda")
157 163
             elif value.__module__ is None:
1  django/db/models/deletion.py
@@ -35,6 +35,7 @@ def set_on_delete(collector, field, sub_objs, using):
35 35
     else:
36 36
         def set_on_delete(collector, field, sub_objs, using):
37 37
             collector.add_field_update(field, value, sub_objs)
  38
+    set_on_delete.deconstruct = lambda: ('django.db.models.SET', (value,), {})
38 39
     return set_on_delete
39 40
 
40 41
 
4  tests/migrations/test_writer.py
@@ -63,6 +63,10 @@ def test_serialize(self):
63 63
         # Functions
64 64
         with six.assertRaisesRegex(self, ValueError, 'Cannot serialize function: lambda'):
65 65
             self.assertSerializedEqual(lambda x: 42)
  66
+        self.assertSerializedEqual(models.SET_NULL)
  67
+        string, imports = MigrationWriter.serialize(models.SET(42))
  68
+        self.assertEqual(string, 'models.SET(42)')
  69
+        self.serialize_round_trip(models.SET(42))
66 70
         # Datetime stuff
67 71
         self.assertSerializedEqual(datetime.datetime.utcnow())
68 72
         self.assertSerializedEqual(datetime.datetime.utcnow)

0 notes on commit d59f199

Please sign in to comment.
Something went wrong with that request. Please try again.