Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Migrated delete doctests. Thanks to Alex Gaynor.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@13778 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 3fe5c6194ce9086b64b9d6a4d2c672c071b50486 1 parent eb8b5dc
Russell Keith-Magee authored September 12, 2010
165  tests/modeltests/delete/models.py
@@ -40,168 +40,3 @@ class E(DefaultRepr, models.Model):
40 40
 class F(DefaultRepr, models.Model):
41 41
     e = models.ForeignKey(E, related_name='f_rel')
42 42
 
43  
-
44  
-__test__ = {'API_TESTS': """
45  
-### Tests for models A,B,C,D ###
46  
-
47  
-## First, test the CollectedObjects data structure directly
48  
-
49  
->>> from django.db.models.query import CollectedObjects
50  
-
51  
->>> g = CollectedObjects()
52  
->>> g.add("key1", 1, "item1", None)
53  
-False
54  
->>> g["key1"]
55  
-{1: 'item1'}
56  
->>> g.add("key2", 1, "item1", "key1")
57  
-False
58  
->>> g.add("key2", 2, "item2", "key1")
59  
-False
60  
->>> g["key2"]
61  
-{1: 'item1', 2: 'item2'}
62  
->>> g.add("key3", 1, "item1", "key1")
63  
-False
64  
->>> g.add("key3", 1, "item1", "key2")
65  
-True
66  
->>> g.ordered_keys()
67  
-['key3', 'key2', 'key1']
68  
-
69  
->>> g.add("key2", 1, "item1", "key3")
70  
-True
71  
->>> g.ordered_keys()
72  
-Traceback (most recent call last):
73  
-    ...
74  
-CyclicDependency: There is a cyclic dependency of items to be processed.
75  
-
76  
-
77  
-## Second, test the usage of CollectedObjects by Model.delete()
78  
-
79  
-# Due to the way that transactions work in the test harness,
80  
-# doing m.delete() here can work but fail in a real situation,
81  
-# since it may delete all objects, but not in the right order.
82  
-# So we manually check that the order of deletion is correct.
83  
-
84  
-# Also, it is possible that the order is correct 'accidentally', due
85  
-# solely to order of imports etc.  To check this, we set the order
86  
-# that 'get_models()' will retrieve to a known 'nice' order, and
87  
-# then try again with a known 'tricky' order.  Slightly naughty
88  
-# access to internals here :-)
89  
-
90  
-# If implementation changes, then the tests may need to be simplified:
91  
-#  - remove the lines that set the .keyOrder and clear the related
92  
-#    object caches
93  
-#  - remove the second set of tests (with a2, b2 etc)
94  
-
95  
->>> from django.db.models.loading import cache
96  
-
97  
->>> def clear_rel_obj_caches(models):
98  
-...     for m in models:
99  
-...         if hasattr(m._meta, '_related_objects_cache'):
100  
-...             del m._meta._related_objects_cache
101  
-
102  
-# Nice order
103  
->>> cache.app_models['delete'].keyOrder = ['a', 'b', 'c', 'd']
104  
->>> clear_rel_obj_caches([A, B, C, D])
105  
-
106  
->>> a1 = A()
107  
->>> a1.save()
108  
->>> b1 = B(a=a1)
109  
->>> b1.save()
110  
->>> c1 = C(b=b1)
111  
->>> c1.save()
112  
->>> d1 = D(c=c1, a=a1)
113  
->>> d1.save()
114  
-
115  
->>> o = CollectedObjects()
116  
->>> a1._collect_sub_objects(o)
117  
->>> o.keys()
118  
-[<class 'modeltests.delete.models.D'>, <class 'modeltests.delete.models.C'>, <class 'modeltests.delete.models.B'>, <class 'modeltests.delete.models.A'>]
119  
->>> a1.delete()
120  
-
121  
-# Same again with a known bad order
122  
->>> cache.app_models['delete'].keyOrder = ['d', 'c', 'b', 'a']
123  
->>> clear_rel_obj_caches([A, B, C, D])
124  
-
125  
->>> a2 = A()
126  
->>> a2.save()
127  
->>> b2 = B(a=a2)
128  
->>> b2.save()
129  
->>> c2 = C(b=b2)
130  
->>> c2.save()
131  
->>> d2 = D(c=c2, a=a2)
132  
->>> d2.save()
133  
-
134  
->>> o = CollectedObjects()
135  
->>> a2._collect_sub_objects(o)
136  
->>> o.keys()
137  
-[<class 'modeltests.delete.models.D'>, <class 'modeltests.delete.models.C'>, <class 'modeltests.delete.models.B'>, <class 'modeltests.delete.models.A'>]
138  
->>> a2.delete()
139  
-
140  
-### Tests for models E,F - nullable related fields ###
141  
-
142  
-## First, test the CollectedObjects data structure directly
143  
-
144  
->>> g = CollectedObjects()
145  
->>> g.add("key1", 1, "item1", None)
146  
-False
147  
->>> g.add("key2", 1, "item1", "key1", nullable=True)
148  
-False
149  
->>> g.add("key1", 1, "item1", "key2")
150  
-True
151  
->>> g.ordered_keys()
152  
-['key1', 'key2']
153  
-
154  
-## Second, test the usage of CollectedObjects by Model.delete()
155  
-
156  
->>> e1 = E()
157  
->>> e1.save()
158  
->>> f1 = F(e=e1)
159  
->>> f1.save()
160  
->>> e1.f = f1
161  
->>> e1.save()
162  
-
163  
-# Since E.f is nullable, we should delete F first (after nulling out
164  
-# the E.f field), then E.
165  
-
166  
->>> o = CollectedObjects()
167  
->>> e1._collect_sub_objects(o)
168  
->>> o.keys()
169  
-[<class 'modeltests.delete.models.F'>, <class 'modeltests.delete.models.E'>]
170  
-
171  
-# temporarily replace the UpdateQuery class to verify that E.f is actually nulled out first
172  
->>> import django.db.models.sql
173  
->>> class LoggingUpdateQuery(django.db.models.sql.UpdateQuery):
174  
-...     def clear_related(self, related_field, pk_list, using):
175  
-...         print "CLEARING FIELD",related_field.name
176  
-...         return super(LoggingUpdateQuery, self).clear_related(related_field, pk_list, using)
177  
->>> original_class = django.db.models.sql.UpdateQuery
178  
->>> django.db.models.sql.UpdateQuery = LoggingUpdateQuery
179  
->>> e1.delete()
180  
-CLEARING FIELD f
181  
-
182  
->>> e2 = E()
183  
->>> e2.save()
184  
->>> f2 = F(e=e2)
185  
->>> f2.save()
186  
->>> e2.f = f2
187  
->>> e2.save()
188  
-
189  
-# Same deal as before, though we are starting from the other object.
190  
-
191  
->>> o = CollectedObjects()
192  
->>> f2._collect_sub_objects(o)
193  
->>> o.keys()
194  
-[<class 'modeltests.delete.models.F'>, <class 'modeltests.delete.models.E'>]
195  
-
196  
->>> f2.delete()
197  
-CLEARING FIELD f
198  
-
199  
-# Put this back to normal
200  
->>> django.db.models.sql.UpdateQuery = original_class
201  
-
202  
-# Restore the app cache to previous condition so that all models are accounted for.
203  
->>> cache.app_models['delete'].keyOrder = ['a', 'b', 'c', 'd', 'e', 'f']
204  
->>> clear_rel_obj_caches([A, B, C, D, E, F])
205  
-
206  
-"""
207  
-}
135  tests/modeltests/delete/tests.py
... ...
@@ -0,0 +1,135 @@
  1
+from django.db.models import sql
  2
+from django.db.models.loading import cache
  3
+from django.db.models.query import CollectedObjects
  4
+from django.db.models.query_utils import CyclicDependency
  5
+from django.test import TestCase
  6
+
  7
+from models import A, B, C, D, E, F
  8
+
  9
+
  10
+class DeleteTests(TestCase):
  11
+    def clear_rel_obj_caches(self, *models):
  12
+        for m in models:
  13
+            if hasattr(m._meta, '_related_objects_cache'):
  14
+                del m._meta._related_objects_cache
  15
+
  16
+    def order_models(self, *models):
  17
+        cache.app_models["delete"].keyOrder = models
  18
+
  19
+    def setUp(self):
  20
+        self.order_models("a", "b", "c", "d", "e", "f")
  21
+        self.clear_rel_obj_caches(A, B, C, D, E, F)
  22
+
  23
+    def tearDown(self):
  24
+        self.order_models("a", "b", "c", "d", "e", "f")
  25
+        self.clear_rel_obj_caches(A, B, C, D, E, F)
  26
+
  27
+    def test_collected_objects(self):
  28
+        g = CollectedObjects()
  29
+        self.assertFalse(g.add("key1", 1, "item1", None))
  30
+        self.assertEqual(g["key1"], {1: "item1"})
  31
+
  32
+        self.assertFalse(g.add("key2", 1, "item1", "key1"))
  33
+        self.assertFalse(g.add("key2", 2, "item2", "key1"))
  34
+
  35
+        self.assertEqual(g["key2"], {1: "item1", 2: "item2"})
  36
+
  37
+        self.assertFalse(g.add("key3", 1, "item1", "key1"))
  38
+        self.assertTrue(g.add("key3", 1, "item1", "key2"))
  39
+        self.assertEqual(g.ordered_keys(), ["key3", "key2", "key1"])
  40
+
  41
+        self.assertTrue(g.add("key2", 1, "item1", "key3"))
  42
+        self.assertRaises(CyclicDependency, g.ordered_keys)
  43
+
  44
+    def test_delete(self):
  45
+        ## Second, test the usage of CollectedObjects by Model.delete()
  46
+
  47
+        # Due to the way that transactions work in the test harness, doing
  48
+        # m.delete() here can work but fail in a real situation, since it may
  49
+        # delete all objects, but not in the right order. So we manually check
  50
+        # that the order of deletion is correct.
  51
+
  52
+        # Also, it is possible that the order is correct 'accidentally', due
  53
+        # solely to order of imports etc.  To check this, we set the order that
  54
+        # 'get_models()' will retrieve to a known 'nice' order, and then try
  55
+        # again with a known 'tricky' order.  Slightly naughty access to
  56
+        # internals here :-)
  57
+
  58
+        # If implementation changes, then the tests may need to be simplified:
  59
+        #  - remove the lines that set the .keyOrder and clear the related
  60
+        #    object caches
  61
+        #  - remove the second set of tests (with a2, b2 etc)
  62
+
  63
+        a1 = A.objects.create()
  64
+        b1 = B.objects.create(a=a1)
  65
+        c1 = C.objects.create(b=b1)
  66
+        d1 = D.objects.create(c=c1, a=a1)
  67
+
  68
+        o = CollectedObjects()
  69
+        a1._collect_sub_objects(o)
  70
+        self.assertEqual(o.keys(), [D, C, B, A])
  71
+        a1.delete()
  72
+
  73
+        # Same again with a known bad order
  74
+        self.order_models("d", "c", "b", "a")
  75
+        self.clear_rel_obj_caches(A, B, C, D)
  76
+
  77
+        a2 = A.objects.create()
  78
+        b2 = B.objects.create(a=a2)
  79
+        c2 = C.objects.create(b=b2)
  80
+        d2 = D.objects.create(c=c2, a=a2)
  81
+
  82
+        o = CollectedObjects()
  83
+        a2._collect_sub_objects(o)
  84
+        self.assertEqual(o.keys(), [D, C, B, A])
  85
+        a2.delete()
  86
+
  87
+    def test_collected_objects_null(self):
  88
+        g = CollectedObjects()
  89
+        self.assertFalse(g.add("key1", 1, "item1", None))
  90
+        self.assertFalse(g.add("key2", 1, "item1", "key1", nullable=True))
  91
+        self.assertTrue(g.add("key1", 1, "item1", "key2"))
  92
+        self.assertEqual(g.ordered_keys(), ["key1", "key2"])
  93
+
  94
+    def test_delete_nullable(self):
  95
+        e1 = E.objects.create()
  96
+        f1 = F.objects.create(e=e1)
  97
+        e1.f = f1
  98
+        e1.save()
  99
+
  100
+        # Since E.f is nullable, we should delete F first (after nulling out
  101
+        # the E.f field), then E.
  102
+
  103
+        o = CollectedObjects()
  104
+        e1._collect_sub_objects(o)
  105
+        self.assertEqual(o.keys(), [F, E])
  106
+
  107
+        # temporarily replace the UpdateQuery class to verify that E.f is
  108
+        # actually nulled out first
  109
+
  110
+        logged = []
  111
+        class LoggingUpdateQuery(sql.UpdateQuery):
  112
+            def clear_related(self, related_field, pk_list, using):
  113
+                logged.append(related_field.name)
  114
+                return super(LoggingUpdateQuery, self).clear_related(related_field, pk_list, using)
  115
+        original = sql.UpdateQuery
  116
+        sql.UpdateQuery = LoggingUpdateQuery
  117
+
  118
+        e1.delete()
  119
+        self.assertEqual(logged, ["f"])
  120
+        logged = []
  121
+
  122
+        e2 = E.objects.create()
  123
+        f2 = F.objects.create(e=e2)
  124
+        e2.f = f2
  125
+        e2.save()
  126
+
  127
+        # Same deal as before, though we are starting from the other object.
  128
+        o = CollectedObjects()
  129
+        f2._collect_sub_objects(o)
  130
+        self.assertEqual(o.keys(), [F, E])
  131
+        f2.delete()
  132
+        self.assertEqual(logged, ["f"])
  133
+        logged = []
  134
+
  135
+        sql.UpdateQuery = original

0 notes on commit 3fe5c61

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