1from south.tests import unittest
2
3from south.creator.changes import AutoChanges, InitialChanges
4from south.migration.base import Migrations
5from south.tests import Monkeypatcher
6from south.creator import freezer
7from south.orm import FakeORM
8from south.v2 import SchemaMigration
9
10try:
11    from django.utils.six.moves import reload_module
12except ImportError:
13    # Older django, no python3 support
14    reload_module = reload
15
16class TestComparison(unittest.TestCase):
17
18    """
19    Tests the comparison methods of startmigration.
20    """
21
22    def test_no_change(self):
23        "Test with a completely unchanged definition."
24
25        self.assertEqual(
26            AutoChanges.different_attributes(
27                ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['southdemo.Lizard']"}),
28                ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['southdemo.Lizard']"}),
29            ),
30            False,
31        )
32
33        self.assertEqual(
34            AutoChanges.different_attributes(
35                ('django.db.models.fields.related.ForeignKey', ['ohhai', 'there'], {'to': "somewhere", "from": "there"}),
36                ('django.db.models.fields.related.ForeignKey', ['ohhai', 'there'], {"from": "there", 'to': "somewhere"}),
37            ),
38            False,
39        )
40
41
42    def test_pos_change(self):
43        "Test with a changed positional argument."
44
45        self.assertEqual(
46            AutoChanges.different_attributes(
47                ('django.db.models.fields.CharField', ['hi'], {'to': "foo"}),
48                ('django.db.models.fields.CharField', [], {'to': "foo"}),
49            ),
50            True,
51        )
52
53        self.assertEqual(
54            AutoChanges.different_attributes(
55                ('django.db.models.fields.CharField', [], {'to': "foo"}),
56                ('django.db.models.fields.CharField', ['bye'], {'to': "foo"}),
57            ),
58            True,
59        )
60
61        self.assertEqual(
62            AutoChanges.different_attributes(
63                ('django.db.models.fields.CharField', ['pi'], {'to': "foo"}),
64                ('django.db.models.fields.CharField', ['pi'], {'to': "foo"}),
65            ),
66            False,
67        )
68
69        self.assertEqual(
70            AutoChanges.different_attributes(
71                ('django.db.models.fields.CharField', ['pisdadad'], {'to': "foo"}),
72                ('django.db.models.fields.CharField', ['pi'], {'to': "foo"}),
73            ),
74            True,
75        )
76
77        self.assertEqual(
78            AutoChanges.different_attributes(
79                ('django.db.models.fields.CharField', ['hi'], {}),
80                ('django.db.models.fields.CharField', [], {}),
81            ),
82            True,
83        )
84
85        self.assertEqual(
86            AutoChanges.different_attributes(
87                ('django.db.models.fields.CharField', [], {}),
88                ('django.db.models.fields.CharField', ['bye'], {}),
89            ),
90            True,
91        )
92
93        self.assertEqual(
94            AutoChanges.different_attributes(
95                ('django.db.models.fields.CharField', ['pi'], {}),
96                ('django.db.models.fields.CharField', ['pi'], {}),
97            ),
98            False,
99        )
100
101        self.assertEqual(
102            AutoChanges.different_attributes(
103                ('django.db.models.fields.CharField', ['pi'], {}),
104                ('django.db.models.fields.CharField', ['45fdfdf'], {}),
105            ),
106            True,
107        )
108
109
110    def test_kwd_change(self):
111        "Test a changed keyword argument"
112
113        self.assertEqual(
114            AutoChanges.different_attributes(
115                ('django.db.models.fields.CharField', ['pi'], {'to': "foo"}),
116                ('django.db.models.fields.CharField', ['pi'], {'to': "blue"}),
117            ),
118            True,
119        )
120
121        self.assertEqual(
122            AutoChanges.different_attributes(
123                ('django.db.models.fields.CharField', [], {'to': "foo"}),
124                ('django.db.models.fields.CharField', [], {'to': "blue"}),
125            ),
126            True,
127        )
128
129        self.assertEqual(
130            AutoChanges.different_attributes(
131                ('django.db.models.fields.CharField', ['b'], {'to': "foo"}),
132                ('django.db.models.fields.CharField', ['b'], {'to': "blue"}),
133            ),
134            True,
135        )
136
137        self.assertEqual(
138            AutoChanges.different_attributes(
139                ('django.db.models.fields.CharField', [], {'to': "foo"}),
140                ('django.db.models.fields.CharField', [], {}),
141            ),
142            True,
143        )
144
145        self.assertEqual(
146            AutoChanges.different_attributes(
147                ('django.db.models.fields.CharField', ['a'], {'to': "foo"}),
148                ('django.db.models.fields.CharField', ['a'], {}),
149            ),
150            True,
151        )
152
153        self.assertEqual(
154            AutoChanges.different_attributes(
155                ('django.db.models.fields.CharField', [], {}),
156                ('django.db.models.fields.CharField', [], {'to': "foo"}),
157            ),
158            True,
159        )
160
161        self.assertEqual(
162            AutoChanges.different_attributes(
163                ('django.db.models.fields.CharField', ['a'], {}),
164                ('django.db.models.fields.CharField', ['a'], {'to': "foo"}),
165            ),
166            True,
167        )
168
169
170
171    def test_backcompat_nochange(self):
172        "Test that the backwards-compatable comparison is working"
173
174        self.assertEqual(
175            AutoChanges.different_attributes(
176                ('models.CharField', [], {}),
177                ('django.db.models.fields.CharField', [], {}),
178            ),
179            False,
180        )
181
182        self.assertEqual(
183            AutoChanges.different_attributes(
184                ('models.CharField', ['ack'], {}),
185                ('django.db.models.fields.CharField', ['ack'], {}),
186            ),
187            False,
188        )
189
190        self.assertEqual(
191            AutoChanges.different_attributes(
192                ('models.CharField', [], {'to':'b'}),
193                ('django.db.models.fields.CharField', [], {'to':'b'}),
194            ),
195            False,
196        )
197
198        self.assertEqual(
199            AutoChanges.different_attributes(
200                ('models.CharField', ['hah'], {'to':'you'}),
201                ('django.db.models.fields.CharField', ['hah'], {'to':'you'}),
202            ),
203            False,
204        )
205
206        self.assertEqual(
207            AutoChanges.different_attributes(
208                ('models.CharField', ['hah'], {'to':'you'}),
209                ('django.db.models.fields.CharField', ['hah'], {'to':'heh'}),
210            ),
211            True,
212        )
213
214        self.assertEqual(
215            AutoChanges.different_attributes(
216                ('models.CharField', ['hah'], {}),
217                ('django.db.models.fields.CharField', [], {'to':"orm['appname.hah']"}),
218            ),
219            False,
220        )
221
222        self.assertEqual(
223            AutoChanges.different_attributes(
224                ('models.CharField', ['hah'], {}),
225                ('django.db.models.fields.CharField', [], {'to':'hah'}),
226            ),
227            True,
228        )
229
230        self.assertEqual(
231            AutoChanges.different_attributes(
232                ('models.CharField', ['hah'], {}),
233                ('django.db.models.fields.CharField', [], {'to':'rrr'}),
234            ),
235            True,
236        )
237
238        self.assertEqual(
239            AutoChanges.different_attributes(
240                ('models.CharField', ['hah'], {}),
241                ('django.db.models.fields.IntField', [], {'to':'hah'}),
242            ),
243            True,
244        )
245
246class TestNonManagedIgnored(Monkeypatcher):
247
248    installed_apps = ["non_managed"]
249
250    full_defs = {
251        'non_managed.legacy': {
252            'Meta': {'object_name': 'Legacy', 'db_table': "'legacy_table'", 'managed': 'False'},
253            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
254            'name': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}),
255            'size': ('django.db.models.fields.IntegerField', [], {})
256        }
257    }
258
259    def test_not_added_init(self):
260
261        migrations = Migrations("non_managed")
262        changes = InitialChanges(migrations)
263        change_list = changes.get_changes()
264        if list(change_list):
265            self.fail("Initial migration creates table for non-managed model")
266
267    def test_not_added_auto(self):
268
269        empty_defs = { }
270        class EmptyMigration(SchemaMigration):
271            "Serves as fake previous migration"
272
273            def forwards(self, orm):
274                pass
275
276            def backwards(self, orm):
277                pass
278
279            models = empty_defs
280
281            complete_apps = ['non_managed']
282
283        migrations = Migrations("non_managed")
284        empty_orm = FakeORM(EmptyMigration, "non_managed")
285        changes = AutoChanges(
286            migrations = migrations,
287            old_defs = empty_defs,
288            old_orm = empty_orm,
289            new_defs = self.full_defs,
290        )
291        change_list = changes.get_changes()
292        if list(change_list):
293            self.fail("Auto migration creates table for non-managed model")
294
295    def test_not_deleted_auto(self):
296
297        empty_defs = { }
298        old_defs = freezer.freeze_apps(["non_managed"])
299        class InitialMigration(SchemaMigration):
300            "Serves as fake previous migration"
301
302            def forwards(self, orm):
303                pass
304
305            def backwards(self, orm):
306                pass
307
308            models = self.full_defs
309
310            complete_apps = ['non_managed']
311
312        migrations = Migrations("non_managed")
313        initial_orm = FakeORM(InitialMigration, "non_managed")
314        changes = AutoChanges(
315            migrations = migrations,
316            old_defs = self.full_defs,
317            old_orm = initial_orm,
318            new_defs = empty_defs,
319        )
320        change_list = changes.get_changes()
321        if list(change_list):
322            self.fail("Auto migration deletes table for non-managed model")
323
324    def test_not_modified_auto(self):
325
326        fake_defs = {
327            'non_managed.legacy': {
328                'Meta': {'object_name': 'Legacy', 'db_table': "'legacy_table'", 'managed': 'False'},
329                'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
330                'name': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}),
331                #'size': ('django.db.models.fields.IntegerField', [], {}) # The "change" is the addition of this field
332            }
333        }
334        class InitialMigration(SchemaMigration):
335            "Serves as fake previous migration"
336
337            def forwards(self, orm):
338                pass
339
340            def backwards(self, orm):
341                pass
342
343            models = fake_defs
344
345            complete_apps = ['non_managed']
346
347        from non_managed import models as dummy_import_to_force_loading_models # TODO: Does needing this indicate a bug in MokeyPatcher?
348        reload_module(dummy_import_to_force_loading_models) # really force...
349
350        migrations = Migrations("non_managed")
351        initial_orm = FakeORM(InitialMigration, "non_managed")
352        changes = AutoChanges(
353            migrations = migrations,
354            old_defs = fake_defs,
355            old_orm = initial_orm,
356            new_defs = self.full_defs
357        )
358        change_list = changes.get_changes()
359        if list(change_list):
360            self.fail("Auto migration changes table for non-managed model")
361