Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Migrated fixtures_regress doctests. Thanks to David Brenneman for the…

… patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@13954 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit b24a55ca7956e35de8f94a52f910dafc0865ab09 1 parent 0856c76
Russell Keith-Magee authored September 28, 2010
1  AUTHORS
@@ -82,6 +82,7 @@ answer newbie questions, and generally made Django that much better:
82 82
     Matías Bordese
83 83
     Sean Brant
84 84
     Andrew Brehaut <http://brehaut.net/blog>
  85
+    David Brennenman <http://davidbrenneman.com>
85 86
     brut.alll@gmail.com
86 87
     bthomas
87 88
     btoll@bestweb.net
249  tests/regressiontests/fixtures_regress/models.py
... ...
@@ -1,7 +1,7 @@
1 1
 from django.db import models, DEFAULT_DB_ALIAS
2 2
 from django.contrib.auth.models import User
3 3
 from django.conf import settings
4  
-import os
  4
+
5 5
 
6 6
 class Animal(models.Model):
7 7
     name = models.CharField(max_length=150)
@@ -15,10 +15,6 @@ class Animal(models.Model):
15 15
     def __unicode__(self):
16 16
         return self.name
17 17
 
18  
-def animal_pre_save_check(signal, sender, instance, **kwargs):
19  
-    "A signal that is used to check the type of data loaded from fixtures"
20  
-    print 'Count = %s (%s)' % (instance.count, type(instance.count))
21  
-    print 'Weight = %s (%s)' % (instance.weight, type(instance.weight))
22 18
 
23 19
 class Plant(models.Model):
24 20
     name = models.CharField(max_length=150)
@@ -40,6 +36,7 @@ def __unicode__(self):
40 36
             name = None
41 37
         return unicode(name) + u' is owned by ' + unicode(self.owner)
42 38
 
  39
+
43 40
 class Absolute(models.Model):
44 41
     name = models.CharField(max_length=40)
45 42
 
@@ -49,19 +46,23 @@ def __init__(self, *args, **kwargs):
49 46
         super(Absolute, self).__init__(*args, **kwargs)
50 47
         Absolute.load_count += 1
51 48
 
  49
+
52 50
 class Parent(models.Model):
53 51
     name = models.CharField(max_length=10)
54 52
 
55 53
     class Meta:
56 54
         ordering = ('id',)
57 55
 
  56
+
58 57
 class Child(Parent):
59 58
     data = models.CharField(max_length=10)
60 59
 
  60
+
61 61
 # Models to regression test #7572
62 62
 class Channel(models.Model):
63 63
     name = models.CharField(max_length=255)
64 64
 
  65
+
65 66
 class Article(models.Model):
66 67
     title = models.CharField(max_length=255)
67 68
     channels = models.ManyToManyField(Channel)
@@ -69,6 +70,7 @@ class Article(models.Model):
69 70
     class Meta:
70 71
         ordering = ('id',)
71 72
 
  73
+
72 74
 # Models to regression test #11428
73 75
 class Widget(models.Model):
74 76
     name = models.CharField(max_length=255)
@@ -79,16 +81,18 @@ class Meta:
79 81
     def __unicode__(self):
80 82
         return self.name
81 83
 
  84
+
82 85
 class WidgetProxy(Widget):
83 86
     class Meta:
84 87
         proxy = True
85 88
 
86  
-# Check for forward references in FKs and M2Ms with natural keys
87 89
 
  90
+# Check for forward references in FKs and M2Ms with natural keys
88 91
 class TestManager(models.Manager):
89 92
     def get_by_natural_key(self, key):
90 93
         return self.get(name=key)
91 94
 
  95
+
92 96
 class Store(models.Model):
93 97
     objects = TestManager()
94 98
     name = models.CharField(max_length=255)
@@ -102,6 +106,7 @@ def __unicode__(self):
102 106
     def natural_key(self):
103 107
         return (self.name,)
104 108
 
  109
+
105 110
 class Person(models.Model):
106 111
     objects = TestManager()
107 112
     name = models.CharField(max_length=255)
@@ -118,6 +123,7 @@ def natural_key(self):
118 123
         return (self.name,)
119 124
     natural_key.dependencies = ['fixtures_regress.store']
120 125
 
  126
+
121 127
 class Book(models.Model):
122 128
     name = models.CharField(max_length=255)
123 129
     author = models.ForeignKey(Person)
@@ -133,10 +139,12 @@ def __unicode__(self):
133 139
             ', '.join(s.name for s in self.stores.all())
134 140
         )
135 141
 
  142
+
136 143
 class NKManager(models.Manager):
137 144
     def get_by_natural_key(self, data):
138 145
         return self.get(data=data)
139 146
 
  147
+
140 148
 class NKChild(Parent):
141 149
     data = models.CharField(max_length=10, unique=True)
142 150
     objects = NKManager()
@@ -147,6 +155,7 @@ def natural_key(self):
147 155
     def __unicode__(self):
148 156
         return u'NKChild %s:%s' % (self.name, self.data)
149 157
 
  158
+
150 159
 class RefToNKChild(models.Model):
151 160
     text = models.CharField(max_length=10)
152 161
     nk_fk = models.ForeignKey(NKChild, related_name='ref_fks')
@@ -159,260 +168,60 @@ def __unicode__(self):
159 168
             ', '.join(str(o) for o in self.nk_m2m.all())
160 169
         )
161 170
 
  171
+
162 172
 # ome models with pathological circular dependencies
163 173
 class Circle1(models.Model):
164 174
     name = models.CharField(max_length=255)
  175
+
165 176
     def natural_key(self):
166 177
         return self.name
167 178
     natural_key.dependencies = ['fixtures_regress.circle2']
168 179
 
  180
+
169 181
 class Circle2(models.Model):
170 182
     name = models.CharField(max_length=255)
  183
+
171 184
     def natural_key(self):
172 185
         return self.name
173 186
     natural_key.dependencies = ['fixtures_regress.circle1']
174 187
 
  188
+
175 189
 class Circle3(models.Model):
176 190
     name = models.CharField(max_length=255)
  191
+
177 192
     def natural_key(self):
178 193
         return self.name
179 194
     natural_key.dependencies = ['fixtures_regress.circle3']
180 195
 
  196
+
181 197
 class Circle4(models.Model):
182 198
     name = models.CharField(max_length=255)
  199
+
183 200
     def natural_key(self):
184 201
         return self.name
185 202
     natural_key.dependencies = ['fixtures_regress.circle5']
186 203
 
  204
+
187 205
 class Circle5(models.Model):
188 206
     name = models.CharField(max_length=255)
  207
+
189 208
     def natural_key(self):
190 209
         return self.name
191 210
     natural_key.dependencies = ['fixtures_regress.circle6']
192 211
 
  212
+
193 213
 class Circle6(models.Model):
194 214
     name = models.CharField(max_length=255)
  215
+
195 216
     def natural_key(self):
196 217
         return self.name
197 218
     natural_key.dependencies = ['fixtures_regress.circle4']
198 219
 
  220
+
199 221
 class ExternalDependency(models.Model):
200 222
     name = models.CharField(max_length=255)
  223
+
201 224
     def natural_key(self):
202 225
         return self.name
203 226
     natural_key.dependencies = ['fixtures_regress.book']
204 227
 
205  
-__test__ = {'API_TESTS':"""
206  
->>> from django.core import management
207  
-
208  
-# Load a fixture that uses PK=1
209  
->>> management.call_command('loaddata', 'sequence', verbosity=0)
210  
-
211  
-# Create a new animal. Without a sequence reset, this new object
212  
-# will take a PK of 1 (on Postgres), and the save will fail.
213  
-# This is a regression test for ticket #3790.
214  
->>> animal = Animal(name='Platypus', latin_name='Ornithorhynchus anatinus', count=2, weight=2.2)
215  
->>> animal.save()
216  
-
217  
-###############################################
218  
-# Regression test for ticket #4558 -- pretty printing of XML fixtures
219  
-# doesn't affect parsing of None values.
220  
-
221  
-# Load a pretty-printed XML fixture with Nulls.
222  
->>> management.call_command('loaddata', 'pretty.xml', verbosity=0)
223  
->>> Stuff.objects.all()
224  
-[<Stuff: None is owned by None>]
225  
-
226  
-###############################################
227  
-# Regression test for ticket #6436 --
228  
-# os.path.join will throw away the initial parts of a path if it encounters
229  
-# an absolute path. This means that if a fixture is specified as an absolute path,
230  
-# we need to make sure we don't discover the absolute path in every fixture directory.
231  
-
232  
->>> load_absolute_path = os.path.join(os.path.dirname(__file__), 'fixtures', 'absolute.json')
233  
->>> management.call_command('loaddata', load_absolute_path, verbosity=0)
234  
->>> Absolute.load_count
235  
-1
236  
-
237  
-###############################################
238  
-# Test for ticket #4371 -- fixture loading fails silently in testcases
239  
-# Validate that error conditions are caught correctly
240  
-
241  
-# redirect stderr for the next few tests...
242  
->>> import sys
243  
->>> savestderr = sys.stderr
244  
->>> sys.stderr = sys.stdout
245  
-
246  
-# Loading data of an unknown format should fail
247  
->>> management.call_command('loaddata', 'bad_fixture1.unkn', verbosity=0)
248  
-Problem installing fixture 'bad_fixture1': unkn is not a known serialization format.
249  
-
250  
-# Loading a fixture file with invalid data using explicit filename
251  
->>> management.call_command('loaddata', 'bad_fixture2.xml', verbosity=0)
252  
-No fixture data found for 'bad_fixture2'. (File format may be invalid.)
253  
-
254  
-# Loading a fixture file with invalid data without file extension
255  
->>> management.call_command('loaddata', 'bad_fixture2', verbosity=0)
256  
-No fixture data found for 'bad_fixture2'. (File format may be invalid.)
257  
-
258  
-# Loading a fixture file with no data returns an error
259  
->>> management.call_command('loaddata', 'empty', verbosity=0)
260  
-No fixture data found for 'empty'. (File format may be invalid.)
261  
-
262  
-# If any of the fixtures contain an error, loading is aborted
263  
-# (Regression for #9011 - error message is correct)
264  
->>> management.call_command('loaddata', 'bad_fixture2', 'animal', verbosity=0)
265  
-No fixture data found for 'bad_fixture2'. (File format may be invalid.)
266  
-
267  
->>> sys.stderr = savestderr
268  
-
269  
-###############################################
270  
-# Test for ticket #7565 -- PostgreSQL sequence resetting checks shouldn't
271  
-# ascend to parent models when inheritance is used (since they are treated
272  
-# individually).
273  
-
274  
->>> management.call_command('loaddata', 'model-inheritance.json', verbosity=0)
275  
-
276  
-###############################################
277  
-# Test for ticket #13030 -- natural keys deserialize with fk to inheriting model
278  
-
279  
-# load data with natural keys
280  
->>> management.call_command('loaddata', 'nk-inheritance.json', verbosity=0)
281  
-
282  
->>> NKChild.objects.get(pk=1)
283  
-<NKChild: NKChild fred:apple>
284  
-
285  
->>> RefToNKChild.objects.get(pk=1)
286  
-<RefToNKChild: my text: Reference to NKChild fred:apple [NKChild fred:apple]>
287  
-
288  
-# ... and again in XML
289  
->>> management.call_command('loaddata', 'nk-inheritance2.xml', verbosity=0)
290  
-
291  
->>> NKChild.objects.get(pk=2)
292  
-<NKChild: NKChild james:banana>
293  
-
294  
->>> RefToNKChild.objects.get(pk=2)
295  
-<RefToNKChild: other text: Reference to NKChild fred:apple [NKChild fred:apple, NKChild james:banana]>
296  
-
297  
-###############################################
298  
-# Test for ticket #7572 -- MySQL has a problem if the same connection is
299  
-# used to create tables, load data, and then query over that data.
300  
-# To compensate, we close the connection after running loaddata.
301  
-# This ensures that a new connection is opened when test queries are issued.
302  
-
303  
->>> management.call_command('loaddata', 'big-fixture.json', verbosity=0)
304  
-
305  
->>> articles = Article.objects.exclude(id=9)
306  
->>> articles.values_list('id', flat=True)
307  
-[1, 2, 3, 4, 5, 6, 7, 8]
308  
-
309  
-# Just for good measure, run the same query again. Under the influence of
310  
-# ticket #7572, this will give a different result to the previous call.
311  
->>> articles.values_list('id', flat=True)
312  
-[1, 2, 3, 4, 5, 6, 7, 8]
313  
-
314  
-###############################################
315  
-# Test for tickets #8298, #9942 - Field values should be coerced into the
316  
-# correct type by the deserializer, not as part of the database write.
317  
-
318  
->>> models.signals.pre_save.connect(animal_pre_save_check)
319  
->>> management.call_command('loaddata', 'animal.xml', verbosity=0)
320  
-Count = 42 (<type 'int'>)
321  
-Weight = 1.2 (<type 'float'>)
322  
-
323  
->>> models.signals.pre_save.disconnect(animal_pre_save_check)
324  
-
325  
-###############################################
326  
-# Regression for #11286 -- Ensure that dumpdata honors the default manager
327  
-# Dump the current contents of the database as a JSON fixture
328  
->>> management.call_command('dumpdata', 'fixtures_regress.animal', format='json')
329  
-[{"pk": 1, "model": "fixtures_regress.animal", "fields": {"count": 3, "weight": 1.2, "name": "Lion", "latin_name": "Panthera leo"}}, {"pk": 2, "model": "fixtures_regress.animal", "fields": {"count": 2, "weight": 2.2, "name": "Platypus", "latin_name": "Ornithorhynchus anatinus"}}, {"pk": 10, "model": "fixtures_regress.animal", "fields": {"count": 42, "weight": 1.2, "name": "Emu", "latin_name": "Dromaius novaehollandiae"}}]
330  
-
331  
-###############################################
332  
-# Regression for #11428 - Proxy models aren't included when you dumpdata
333  
-
334  
-# Flush out the database first
335  
->>> management.call_command('reset', 'fixtures_regress', interactive=False, verbosity=0)
336  
-
337  
-# Create an instance of the concrete class
338  
->>> Widget(name='grommet').save()
339  
-
340  
-# Dump data for the entire app. The proxy class shouldn't be included
341  
->>> management.call_command('dumpdata', 'fixtures_regress.widget', 'fixtures_regress.widgetproxy', format='json')
342  
-[{"pk": 1, "model": "fixtures_regress.widget", "fields": {"name": "grommet"}}]
343  
-
344  
-###############################################
345  
-# Check that natural key requirements are taken into account
346  
-# when serializing models
347  
->>> management.call_command('loaddata', 'forward_ref_lookup.json', verbosity=0)
348  
-
349  
->>> management.call_command('dumpdata', 'fixtures_regress.book', 'fixtures_regress.person', 'fixtures_regress.store', verbosity=0, use_natural_keys=True)
350  
-[{"pk": 2, "model": "fixtures_regress.store", "fields": {"name": "Amazon"}}, {"pk": 3, "model": "fixtures_regress.store", "fields": {"name": "Borders"}}, {"pk": 4, "model": "fixtures_regress.person", "fields": {"name": "Neal Stephenson"}}, {"pk": 1, "model": "fixtures_regress.book", "fields": {"stores": [["Amazon"], ["Borders"]], "name": "Cryptonomicon", "author": ["Neal Stephenson"]}}]
351  
-
352  
-# Now lets check the dependency sorting explicitly
353  
-
354  
-# It doesn't matter what order you mention the models
355  
-# Store *must* be serialized before then Person, and both
356  
-# must be serialized before Book.
357  
->>> from django.core.management.commands.dumpdata import sort_dependencies
358  
->>> sort_dependencies([('fixtures_regress', [Book, Person, Store])])
359  
-[<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>]
360  
-
361  
->>> sort_dependencies([('fixtures_regress', [Book, Store, Person])])
362  
-[<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>]
363  
-
364  
->>> sort_dependencies([('fixtures_regress', [Store, Book, Person])])
365  
-[<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>]
366  
-
367  
->>> sort_dependencies([('fixtures_regress', [Store, Person, Book])])
368  
-[<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>]
369  
-
370  
->>> sort_dependencies([('fixtures_regress', [Person, Book, Store])])
371  
-[<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>]
372  
-
373  
->>> sort_dependencies([('fixtures_regress', [Person, Store, Book])])
374  
-[<class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>]
375  
-
376  
-# A dangling dependency - assume the user knows what they are doing.
377  
->>> sort_dependencies([('fixtures_regress', [Person, Circle1, Store, Book])])
378  
-[<class 'regressiontests.fixtures_regress.models.Circle1'>, <class 'regressiontests.fixtures_regress.models.Store'>, <class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>]
379  
-
380  
-# A tight circular dependency
381  
->>> sort_dependencies([('fixtures_regress', [Person, Circle2, Circle1, Store, Book])])
382  
-Traceback (most recent call last):
383  
-...
384  
-CommandError: Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2 in serialized app list.
385  
-
386  
->>> sort_dependencies([('fixtures_regress', [Circle1, Book, Circle2])])
387  
-Traceback (most recent call last):
388  
-...
389  
-CommandError: Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2 in serialized app list.
390  
-
391  
-# A self referential dependency
392  
->>> sort_dependencies([('fixtures_regress', [Book, Circle3])])
393  
-Traceback (most recent call last):
394  
-...
395  
-CommandError: Can't resolve dependencies for fixtures_regress.Circle3 in serialized app list.
396  
-
397  
-# A long circular dependency
398  
->>> sort_dependencies([('fixtures_regress', [Person, Circle2, Circle1, Circle3, Store, Book])])
399  
-Traceback (most recent call last):
400  
-...
401  
-CommandError: Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2, fixtures_regress.Circle3 in serialized app list.
402  
-
403  
-# A dependency on a normal, non-natural-key model
404  
->>> sort_dependencies([('fixtures_regress', [Person, ExternalDependency, Book])])
405  
-[<class 'regressiontests.fixtures_regress.models.Person'>, <class 'regressiontests.fixtures_regress.models.Book'>, <class 'regressiontests.fixtures_regress.models.ExternalDependency'>]
406  
-
407  
-###############################################
408  
-# Check that normal primary keys still work
409  
-# on a model with natural key capabilities
410  
-
411  
->>> management.call_command('loaddata', 'non_natural_1.json', verbosity=0)
412  
->>> management.call_command('loaddata', 'non_natural_2.xml', verbosity=0)
413  
-
414  
->>> Book.objects.all()
415  
-[<Book: Cryptonomicon by Neal Stephenson (available at Amazon, Borders)>, <Book: Ender's Game by Orson Scott Card (available at Collins Bookstore)>, <Book: Permutation City by Greg Egan (available at Angus and Robertson)>]
416  
-
417  
-"""}
418  
-
564  tests/regressiontests/fixtures_regress/tests.py
... ...
@@ -0,0 +1,564 @@
  1
+# -*- coding: utf-8 -*-
  2
+# Unittests for fixtures.
  3
+import os
  4
+import sys
  5
+try:
  6
+    from cStringIO import StringIO
  7
+except ImportError:
  8
+    from StringIO import StringIO
  9
+
  10
+from django.core import management
  11
+from django.core.management.commands.dumpdata import sort_dependencies
  12
+from django.core.management.base import CommandError
  13
+from django.db.models import signals
  14
+from django.test import TestCase
  15
+
  16
+from models import Animal, Stuff
  17
+from models import Absolute, Parent, Child
  18
+from models import Article, Widget
  19
+from models import Store, Person, Book
  20
+from models import NKChild, RefToNKChild
  21
+from models import Circle1, Circle2, Circle3
  22
+from models import ExternalDependency
  23
+
  24
+
  25
+pre_save_checks = []
  26
+def animal_pre_save_check(signal, sender, instance, **kwargs):
  27
+    "A signal that is used to check the type of data loaded from fixtures"
  28
+    pre_save_checks.append(
  29
+        (
  30
+            'Count = %s (%s)' % (instance.count, type(instance.count)),
  31
+            'Weight = %s (%s)' % (instance.weight, type(instance.weight)),
  32
+        )
  33
+    )
  34
+
  35
+
  36
+class TestFixtures(TestCase):
  37
+    def test_duplicate_pk(self):
  38
+        """
  39
+        This is a regression test for ticket #3790.
  40
+        """
  41
+        # Load a fixture that uses PK=1
  42
+        management.call_command(
  43
+            'loaddata',
  44
+            'sequence',
  45
+            verbosity=0,
  46
+            commit=False
  47
+        )
  48
+
  49
+        # Create a new animal. Without a sequence reset, this new object
  50
+        # will take a PK of 1 (on Postgres), and the save will fail.
  51
+
  52
+        animal = Animal(
  53
+            name='Platypus',
  54
+            latin_name='Ornithorhynchus anatinus',
  55
+            count=2,
  56
+            weight=2.2
  57
+        )
  58
+        animal.save()
  59
+        self.assertEqual(animal.id, 2)
  60
+
  61
+    def test_pretty_print_xml(self):
  62
+        """
  63
+        Regression test for ticket #4558 -- pretty printing of XML fixtures
  64
+        doesn't affect parsing of None values.
  65
+        """
  66
+        # Load a pretty-printed XML fixture with Nulls.
  67
+        management.call_command(
  68
+            'loaddata',
  69
+            'pretty.xml',
  70
+            verbosity=0,
  71
+            commit=False
  72
+        )
  73
+        self.assertEqual(Stuff.objects.all()[0].name, None)
  74
+        self.assertEqual(Stuff.objects.all()[0].owner, None)
  75
+
  76
+    def test_absolute_path(self):
  77
+        """
  78
+        Regression test for ticket #6436 --
  79
+        os.path.join will throw away the initial parts of a path if it
  80
+        encounters an absolute path.
  81
+        This means that if a fixture is specified as an absolute path,
  82
+        we need to make sure we don't discover the absolute path in every
  83
+        fixture directory.
  84
+        """
  85
+        load_absolute_path = os.path.join(
  86
+            os.path.dirname(__file__),
  87
+            'fixtures',
  88
+            'absolute.json'
  89
+        )
  90
+        management.call_command(
  91
+            'loaddata',
  92
+            load_absolute_path,
  93
+            verbosity=0,
  94
+            commit=False
  95
+        )
  96
+        self.assertEqual(Absolute.load_count, 1)
  97
+
  98
+
  99
+    def test_unknown_format(self):
  100
+        """
  101
+        Test for ticket #4371 -- Loading data of an unknown format should fail
  102
+        Validate that error conditions are caught correctly
  103
+        """
  104
+        stderr = StringIO()
  105
+        management.call_command(
  106
+            'loaddata',
  107
+            'bad_fixture1.unkn',
  108
+            verbosity=0,
  109
+            commit=False,
  110
+            stderr=stderr,
  111
+        )
  112
+        self.assertEqual(
  113
+            stderr.getvalue(),
  114
+            "Problem installing fixture 'bad_fixture1': unkn is not a known serialization format.\n"
  115
+        )
  116
+
  117
+    def test_invalid_data(self):
  118
+        """
  119
+        Test for ticket #4371 -- Loading a fixture file with invalid data
  120
+        using explicit filename.
  121
+        Validate that error conditions are caught correctly
  122
+        """
  123
+        stderr = StringIO()
  124
+        management.call_command(
  125
+            'loaddata',
  126
+            'bad_fixture2.xml',
  127
+            verbosity=0,
  128
+            commit=False,
  129
+            stderr=stderr,
  130
+        )
  131
+        self.assertEqual(
  132
+            stderr.getvalue(),
  133
+            "No fixture data found for 'bad_fixture2'. (File format may be invalid.)\n"
  134
+        )
  135
+
  136
+    def test_invalid_data_no_ext(self):
  137
+        """
  138
+        Test for ticket #4371 -- Loading a fixture file with invalid data
  139
+        without file extension.
  140
+        Validate that error conditions are caught correctly
  141
+        """
  142
+        stderr = StringIO()
  143
+        management.call_command(
  144
+            'loaddata',
  145
+            'bad_fixture2',
  146
+            verbosity=0,
  147
+            commit=False,
  148
+            stderr=stderr,
  149
+        )
  150
+        self.assertEqual(
  151
+            stderr.getvalue(),
  152
+            "No fixture data found for 'bad_fixture2'. (File format may be invalid.)\n"
  153
+        )
  154
+
  155
+    def test_empty(self):
  156
+        """
  157
+        Test for ticket #4371 -- Loading a fixture file with no data returns an error.
  158
+        Validate that error conditions are caught correctly
  159
+        """
  160
+        stderr = StringIO()
  161
+        management.call_command(
  162
+            'loaddata',
  163
+            'empty',
  164
+            verbosity=0,
  165
+            commit=False,
  166
+            stderr=stderr,
  167
+        )
  168
+        self.assertEqual(
  169
+            stderr.getvalue(),
  170
+            "No fixture data found for 'empty'. (File format may be invalid.)\n"
  171
+        )
  172
+
  173
+    def test_abort_loaddata_on_error(self):
  174
+        """
  175
+        Test for ticket #4371 -- If any of the fixtures contain an error,
  176
+        loading is aborted.
  177
+        Validate that error conditions are caught correctly
  178
+        """
  179
+        stderr = StringIO()
  180
+        management.call_command(
  181
+            'loaddata',
  182
+            'empty',
  183
+            verbosity=0,
  184
+            commit=False,
  185
+            stderr=stderr,
  186
+        )
  187
+        self.assertEqual(
  188
+            stderr.getvalue(),
  189
+            "No fixture data found for 'empty'. (File format may be invalid.)\n"
  190
+        )
  191
+
  192
+    def test_error_message(self):
  193
+        """
  194
+        (Regression for #9011 - error message is correct)
  195
+        """
  196
+        stderr = StringIO()
  197
+        management.call_command(
  198
+            'loaddata',
  199
+            'bad_fixture2',
  200
+            'animal',
  201
+            verbosity=0,
  202
+            commit=False,
  203
+            stderr=stderr,
  204
+        )
  205
+        self.assertEqual(
  206
+            stderr.getvalue(),
  207
+            "No fixture data found for 'bad_fixture2'. (File format may be invalid.)\n"
  208
+        )
  209
+
  210
+    def test_pg_sequence_resetting_checks(self):
  211
+        """
  212
+        Test for ticket #7565 -- PostgreSQL sequence resetting checks shouldn't
  213
+        ascend to parent models when inheritance is used
  214
+        (since they are treated individually).
  215
+        """
  216
+        management.call_command(
  217
+            'loaddata',
  218
+            'model-inheritance.json',
  219
+            verbosity=0,
  220
+            commit=False
  221
+        )
  222
+        self.assertEqual(Parent.objects.all()[0].id, 1)
  223
+        self.assertEqual(Child.objects.all()[0].id, 1)
  224
+
  225
+    def test_close_connection_after_loaddata(self):
  226
+        """
  227
+        Test for ticket #7572 -- MySQL has a problem if the same connection is
  228
+        used to create tables, load data, and then query over that data.
  229
+        To compensate, we close the connection after running loaddata.
  230
+        This ensures that a new connection is opened when test queries are
  231
+        issued.
  232
+        """
  233
+        management.call_command(
  234
+            'loaddata',
  235
+            'big-fixture.json',
  236
+            verbosity=0,
  237
+            commit=False
  238
+        )
  239
+        articles = Article.objects.exclude(id=9)
  240
+        self.assertEqual(
  241
+            articles.values_list('id', flat=True).__repr__(),
  242
+            "[1, 2, 3, 4, 5, 6, 7, 8]"
  243
+        )
  244
+        # Just for good measure, run the same query again.
  245
+        # Under the influence of ticket #7572, this will
  246
+        # give a different result to the previous call.
  247
+        self.assertEqual(
  248
+            articles.values_list('id', flat=True).__repr__(),
  249
+            "[1, 2, 3, 4, 5, 6, 7, 8]"
  250
+        )
  251
+
  252
+    def test_field_value_coerce(self):
  253
+        """
  254
+        Test for tickets #8298, #9942 - Field values should be coerced into the
  255
+        correct type by the deserializer, not as part of the database write.
  256
+        """
  257
+        global pre_save_checks
  258
+        pre_save_checks = []
  259
+        signals.pre_save.connect(animal_pre_save_check)
  260
+        management.call_command(
  261
+            'loaddata',
  262
+            'animal.xml',
  263
+            verbosity=0,
  264
+            commit=False,
  265
+        )
  266
+        self.assertEqual(
  267
+            pre_save_checks,
  268
+            [
  269
+                ("Count = 42 (<type 'int'>)", "Weight = 1.2 (<type 'float'>)")
  270
+            ]
  271
+        )
  272
+        signals.pre_save.disconnect(animal_pre_save_check)
  273
+
  274
+    def test_dumpdata_uses_default_manager(self):
  275
+        """
  276
+        Regression for #11286
  277
+        Ensure that dumpdata honors the default manager
  278
+        Dump the current contents of the database as a JSON fixture
  279
+        """
  280
+        management.call_command(
  281
+            'loaddata',
  282
+            'animal.xml',
  283
+            verbosity=0,
  284
+            commit=False,
  285
+        )
  286
+        management.call_command(
  287
+            'loaddata',
  288
+            'sequence.json',
  289
+            verbosity=0,
  290
+            commit=False,
  291
+        )
  292
+        animal = Animal(
  293
+            name='Platypus',
  294
+            latin_name='Ornithorhynchus anatinus',
  295
+            count=2,
  296
+            weight=2.2
  297
+        )
  298
+        animal.save()
  299
+
  300
+        stdout = StringIO()
  301
+        management.call_command(
  302
+            'dumpdata',
  303
+            'fixtures_regress.animal',
  304
+            format='json',
  305
+            stdout=stdout
  306
+        )
  307
+        self.assertEqual(
  308
+            stdout.getvalue(),
  309
+            """[{"pk": 1, "model": "fixtures_regress.animal", "fields": {"count": 3, "weight": 1.2, "name": "Lion", "latin_name": "Panthera leo"}}, {"pk": 10, "model": "fixtures_regress.animal", "fields": {"count": 42, "weight": 1.2, "name": "Emu", "latin_name": "Dromaius novaehollandiae"}}, {"pk": 11, "model": "fixtures_regress.animal", "fields": {"count": 2, "weight": 2.2000000000000002, "name": "Platypus", "latin_name": "Ornithorhynchus anatinus"}}]"""
  310
+        )
  311
+
  312
+    def test_proxy_model_included(self):
  313
+        """
  314
+        Regression for #11428 - Proxy models aren't included when you dumpdata
  315
+        """
  316
+        stdout = StringIO()
  317
+        # Create an instance of the concrete class
  318
+        Widget(name='grommet').save()
  319
+        management.call_command(
  320
+            'dumpdata',
  321
+            'fixtures_regress.widget',
  322
+            'fixtures_regress.widgetproxy',
  323
+            format='json',
  324
+            stdout=stdout
  325
+        )
  326
+        self.assertEqual(
  327
+            stdout.getvalue(),
  328
+            """[{"pk": 1, "model": "fixtures_regress.widget", "fields": {"name": "grommet"}}]"""
  329
+            )
  330
+
  331
+
  332
+class NaturalKeyFixtureTests(TestCase):
  333
+    def assertRaisesMessage(self, exc, msg, func, *args, **kwargs):
  334
+        try:
  335
+            func(*args, **kwargs)
  336
+        except Exception, e:
  337
+            self.assertEqual(msg, str(e))
  338
+            self.assertTrue(isinstance(e, exc), "Expected %s, got %s" % (exc, type(e)))
  339
+
  340
+    def test_nk_deserialize(self):
  341
+        """
  342
+        Test for ticket #13030 - Python based parser version
  343
+        natural keys deserialize with fk to inheriting model
  344
+        """
  345
+        management.call_command(
  346
+            'loaddata',
  347
+            'model-inheritance.json',
  348
+            verbosity=0,
  349
+            commit=False
  350
+        )
  351
+        management.call_command(
  352
+            'loaddata',
  353
+            'nk-inheritance.json',
  354
+            verbosity=0,
  355
+            commit=False
  356
+        )
  357
+        self.assertEqual(
  358
+            NKChild.objects.get(pk=1).data,
  359
+            'apple'
  360
+        )
  361
+
  362
+        self.assertEqual(
  363
+            RefToNKChild.objects.get(pk=1).nk_fk.data,
  364
+            'apple'
  365
+        )
  366
+
  367
+    def test_nk_deserialize_xml(self):
  368
+        """
  369
+        Test for ticket #13030 - XML version
  370
+        natural keys deserialize with fk to inheriting model
  371
+        """
  372
+        management.call_command(
  373
+            'loaddata',
  374
+            'model-inheritance.json',
  375
+            verbosity=0,
  376
+            commit=False
  377
+        )
  378
+        management.call_command(
  379
+            'loaddata',
  380
+            'nk-inheritance.json',
  381
+            verbosity=0,
  382
+            commit=False
  383
+        )
  384
+        management.call_command(
  385
+            'loaddata',
  386
+            'nk-inheritance2.xml',
  387
+            verbosity=0,
  388
+            commit=False
  389
+        )
  390
+        self.assertEqual(
  391
+            NKChild.objects.get(pk=2).data,
  392
+            'banana'
  393
+        )
  394
+        self.assertEqual(
  395
+            RefToNKChild.objects.get(pk=2).nk_fk.data,
  396
+            'apple'
  397
+        )
  398
+
  399
+    def test_nk_on_serialize(self):
  400
+        """
  401
+        Check that natural key requirements are taken into account
  402
+        when serializing models
  403
+        """
  404
+        management.call_command(
  405
+            'loaddata',
  406
+            'forward_ref_lookup.json',
  407
+            verbosity=0,
  408
+            commit=False
  409
+            )
  410
+
  411
+        stdout = StringIO()
  412
+        management.call_command(
  413
+            'dumpdata',
  414
+            'fixtures_regress.book',
  415
+            'fixtures_regress.person',
  416
+            'fixtures_regress.store',
  417
+            verbosity=0,
  418
+            format='json',
  419
+            use_natural_keys=True,
  420
+            stdout=stdout,
  421
+        )
  422
+        self.assertEqual(
  423
+            stdout.getvalue(),
  424
+            """[{"pk": 2, "model": "fixtures_regress.store", "fields": {"name": "Amazon"}}, {"pk": 3, "model": "fixtures_regress.store", "fields": {"name": "Borders"}}, {"pk": 4, "model": "fixtures_regress.person", "fields": {"name": "Neal Stephenson"}}, {"pk": 1, "model": "fixtures_regress.book", "fields": {"stores": [["Amazon"], ["Borders"]], "name": "Cryptonomicon", "author": ["Neal Stephenson"]}}]"""
  425
+        )
  426
+
  427
+    def test_dependency_sorting(self):
  428
+        """
  429
+        Now lets check the dependency sorting explicitly
  430
+        It doesn't matter what order you mention the models
  431
+        Store *must* be serialized before then Person, and both
  432
+        must be serialized before Book.
  433
+        """
  434
+        sorted_deps = sort_dependencies(
  435
+            [('fixtures_regress', [Book, Person, Store])]
  436
+        )
  437
+        self.assertEqual(
  438
+            sorted_deps,
  439
+            [Store, Person, Book]
  440
+        )
  441
+
  442
+    def test_dependency_sorting_2(self):
  443
+        sorted_deps = sort_dependencies(
  444
+            [('fixtures_regress', [Book, Store, Person])]
  445
+        )
  446
+        self.assertEqual(
  447
+            sorted_deps,
  448
+            [Store, Person, Book]
  449
+        )
  450
+
  451
+    def test_dependency_sorting_3(self):
  452
+        sorted_deps = sort_dependencies(
  453
+            [('fixtures_regress', [Store, Book, Person])]
  454
+        )
  455
+        self.assertEqual(
  456
+            sorted_deps,
  457
+            [Store, Person, Book]
  458
+        )
  459
+
  460
+    def test_dependency_sorting_4(self):
  461
+        sorted_deps = sort_dependencies(
  462
+            [('fixtures_regress', [Store, Person, Book])]
  463
+        )
  464
+        self.assertEqual(
  465
+            sorted_deps,
  466
+            [Store, Person, Book]
  467
+        )
  468
+
  469
+    def test_dependency_sorting_5(self):
  470
+        sorted_deps = sort_dependencies(
  471
+            [('fixtures_regress', [Person, Book, Store])]
  472
+        )
  473
+        self.assertEqual(
  474
+            sorted_deps,
  475
+            [Store, Person, Book]
  476
+        )
  477
+
  478
+    def test_dependency_sorting_6(self):
  479
+        sorted_deps = sort_dependencies(
  480
+            [('fixtures_regress', [Person, Store, Book])]
  481
+        )
  482
+        self.assertEqual(
  483
+            sorted_deps,
  484
+            [Store, Person, Book]
  485
+        )
  486
+
  487
+    def test_dependency_sorting_dangling(self):
  488
+        sorted_deps = sort_dependencies(
  489
+            [('fixtures_regress', [Person, Circle1, Store, Book])]
  490
+        )
  491
+        self.assertEqual(
  492
+            sorted_deps,
  493
+            [Circle1, Store, Person, Book]
  494
+        )
  495
+
  496
+    def test_dependency_sorting_tight_circular(self):
  497
+        self.assertRaisesMessage(
  498
+            CommandError,
  499
+            """Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2 in serialized app list.""",
  500
+            sort_dependencies,
  501
+            [('fixtures_regress', [Person, Circle2, Circle1, Store, Book])],
  502
+        )
  503
+
  504
+    def test_dependency_sorting_tight_circular_2(self):
  505
+        self.assertRaisesMessage(
  506
+            CommandError,
  507
+            """Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2 in serialized app list.""",
  508
+            sort_dependencies,
  509
+            [('fixtures_regress', [Circle1, Book, Circle2])],
  510
+        )
  511
+
  512
+    def test_dependency_self_referential(self):
  513
+        self.assertRaisesMessage(
  514
+            CommandError,
  515
+            """Can't resolve dependencies for fixtures_regress.Circle3 in serialized app list.""",
  516
+            sort_dependencies,
  517
+            [('fixtures_regress', [Book, Circle3])],
  518
+        )
  519
+
  520
+    def test_dependency_sorting_long(self):
  521
+        self.assertRaisesMessage(
  522
+            CommandError,
  523
+            """Can't resolve dependencies for fixtures_regress.Circle1, fixtures_regress.Circle2, fixtures_regress.Circle3 in serialized app list.""",
  524
+            sort_dependencies,
  525
+            [('fixtures_regress', [Person, Circle2, Circle1, Circle3, Store, Book])],
  526
+        )
  527
+
  528
+    def test_dependency_sorting_normal(self):
  529
+        sorted_deps = sort_dependencies(
  530
+            [('fixtures_regress', [Person, ExternalDependency, Book])]
  531
+        )
  532
+        self.assertEqual(
  533
+            sorted_deps,
  534
+            [Person, Book, ExternalDependency]
  535
+        )
  536
+
  537
+    def test_normal_pk(self):
  538
+        """
  539
+        Check that normal primary keys still work
  540
+        on a model with natural key capabilities
  541
+        """
  542
+        management.call_command(
  543
+            'loaddata',
  544
+            'non_natural_1.json',
  545
+            verbosity=0,
  546
+            commit=False
  547
+        )
  548
+        management.call_command(
  549
+            'loaddata',
  550
+            'forward_ref_lookup.json',
  551
+            verbosity=0,
  552
+            commit=False
  553
+        )
  554
+        management.call_command(
  555
+            'loaddata',
  556
+            'non_natural_2.xml',
  557
+            verbosity=0,
  558
+            commit=False
  559
+        )
  560
+        books = Book.objects.all()
  561
+        self.assertEqual(
  562
+            books.__repr__(),
  563
+            """[<Book: Cryptonomicon by Neal Stephenson (available at Amazon, Borders)>, <Book: Ender's Game by Orson Scott Card (available at Collins Bookstore)>, <Book: Permutation City by Greg Egan (available at Angus and Robertson)>]"""
  564
+        )

0 notes on commit b24a55c

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