1from PyObjCTools.TestSupport import *
2import objc
3
4NSObject = objc.lookUpClass('NSObject')
5
6class TestUseKVOObserver (NSObject):
7    def init(self):
8        self = super(TestUseKVOObserver, self).init()
9        if self is None:
10            return None
11
12        self.observations = []
13        return self
14
15    def observeValueForKeyPath_ofObject_change_context_(self, path, object, change, context):
16        self.observations.append((path, object))
17
18
19class TestUseKVO (TestCase):
20    def setUp(self):
21        self._previous = objc.setUseKVOForSetattr(True)
22
23    def tearDown(self):
24        objc.setUseKVOForSetattr(self._previous)
25
26    def areChangesEmitted(self, object):
27        observer = TestUseKVOObserver.alloc().init()
28        object.addObserver_forKeyPath_options_context_(
29                observer, "value", 0, 0)
30
31        try:
32            object.value = 42
33
34        finally:
35            object.removeObserver_forKeyPath_(observer, "value")
36
37        return len(observer.observations) > 0
38
39    def assertChangesEmitted(self, object):
40        if not self.areChangesEmitted(object):
41            self.fail("Setting 'value' on %r doesn't emit KVO" % object)
42
43    def assertNoChangesEmitted(self, object):
44        if self.areChangesEmitted(object):
45            self.fail("Setting 'value' on %r does emit KVO" % object)
46
47    def testPythonAttr_True(self):
48        objc.setUseKVOForSetattr(True)
49
50        class OCTestUseKVO1 (NSObject):
51            pass
52
53        self.assertTrue(OCTestUseKVO1.__useKVO__)
54
55        obj = OCTestUseKVO1.alloc().init()
56        self.assertChangesEmitted(obj)
57
58    def testObjCAttr_True(self):
59        objc.setUseKVOForSetattr(True)
60
61        class OCTestUseKVO2 (NSObject):
62            value = objc.ivar()
63
64        self.assertTrue(OCTestUseKVO2.__useKVO__)
65
66        obj = OCTestUseKVO2.alloc().init()
67        self.assertChangesEmitted(obj)
68
69
70    def testPythonAttr_False(self):
71        objc.setUseKVOForSetattr(False)
72
73        class OCTestUseKVO3 (NSObject):
74            pass
75
76        self.assertFalse(OCTestUseKVO3.__useKVO__)
77        obj = OCTestUseKVO3.alloc().init()
78        self.assertNoChangesEmitted(obj)
79
80    def testObjCAttr_False(self):
81        objc.setUseKVOForSetattr(False)
82
83        class OCTestUseKVO4 (NSObject):
84            value = objc.ivar()
85
86        self.assertFalse(OCTestUseKVO4.__useKVO__)
87        obj = OCTestUseKVO4.alloc().init()
88        self.assertNoChangesEmitted(obj)
89
90
91if __name__ == "__main__":
92    main()
93