1
2from south.tests import Monkeypatcher, skipUnless
3from south.modelsinspector import (convert_on_delete_handler, get_value,
4    IsDefault, models, value_clean)
5
6from fakeapp.models import HorribleModel, get_sentinel_object
7
8
9on_delete_is_available = hasattr(models, "PROTECT") # models here is django.db.models
10skipUnlessOnDeleteAvailable = skipUnless(on_delete_is_available, "not testing on_delete -- not available on Django<1.3")
11
12class TestModelInspector(Monkeypatcher):
13
14    """
15    Tests if the various parts of the modelinspector work.
16    """
17
18    def test_get_value(self):
19
20        # Let's start nicely.
21        name = HorribleModel._meta.get_field_by_name("name")[0]
22        slug = HorribleModel._meta.get_field_by_name("slug")[0]
23        user = HorribleModel._meta.get_field_by_name("user")[0]
24
25        # Simple int retrieval
26        self.assertEqual(
27            get_value(name, ["max_length", {}]),
28            "255",
29        )
30
31        # Bool retrieval
32        self.assertEqual(
33            get_value(slug, ["unique", {}]),
34            "True",
35        )
36
37        # String retrieval
38        self.assertEqual(
39            get_value(user, ["rel.related_name", {}]),
40            "'horribles'",
41        )
42
43        # Default triggering
44        self.assertEqual(
45            get_value(slug, ["unique", {"default": False}]),
46            "True",
47        )
48        self.assertRaises(
49            IsDefault,
50            get_value,
51            slug,
52            ["unique", {"default": True}],
53        )
54
55    @skipUnlessOnDeleteAvailable
56    def test_get_value_on_delete(self):
57
58        # First validate the FK fields with on_delete options
59        o_set_null_on_delete = HorribleModel._meta.get_field_by_name("o_set_null_on_delete")[0]
60        o_cascade_delete = HorribleModel._meta.get_field_by_name("o_cascade_delete")[0]
61        o_protect = HorribleModel._meta.get_field_by_name("o_protect")[0]
62        o_default_on_delete = HorribleModel._meta.get_field_by_name("o_default_on_delete")[0]
63        o_set_on_delete_function = HorribleModel._meta.get_field_by_name("o_set_on_delete_function")[0]
64        o_set_on_delete_value = HorribleModel._meta.get_field_by_name("o_set_on_delete_value")[0]
65        o_no_action_on_delete = HorribleModel._meta.get_field_by_name("o_no_action_on_delete")[0]
66        # TODO this is repeated from the introspection_details in modelsinspector:
67        # better to refactor that so we can reference these settings, in case they
68        # must change at some point.
69        on_delete = ["rel.on_delete", {"default": models.CASCADE, "is_django_function": True, "converter": convert_on_delete_handler, }]
70
71        # Foreign Key cascade update/delete
72        self.assertRaises(
73            IsDefault,
74            get_value,
75            o_cascade_delete,
76            on_delete,
77        )
78        self.assertEqual(
79            get_value(o_protect, on_delete),
80            "models.PROTECT",
81        )
82        self.assertEqual(
83            get_value(o_no_action_on_delete, on_delete),
84            "models.DO_NOTHING",
85        )
86        self.assertEqual(
87            get_value(o_set_null_on_delete, on_delete),
88            "models.SET_NULL",
89        )
90        self.assertEqual(
91            get_value(o_default_on_delete, on_delete),
92            "models.SET_DEFAULT",
93        )
94        # For now o_set_on_delete raises, see modelsinspector.py
95        #self.assertEqual(
96        #    get_value(o_set_on_delete_function, on_delete),
97        #    "models.SET(get_sentinel_object)",
98        #)
99        self.assertRaises(
100            ValueError,
101            get_value,
102            o_set_on_delete_function,
103            on_delete,
104        )
105        self.assertEqual(
106            get_value(o_set_on_delete_value, on_delete),
107            "models.SET(%s)" % value_clean(get_sentinel_object()),
108        )
109