Commits

Ronald Oussoren  committed f1d4653

object_property test updates

  • Participants
  • Parent commits 5bc325e

Comments (0)

Files changed (5)

File pyobjc-core/Lib/objc/_properties.py

 if sys.version_info[0] == 2:
     range = xrange
 
+else:
+    long = int
+
 
 def attrsetter(prop, name, copy):
     if copy:
     def _wrapped(self):
         return self.__wrapped.__getvalue__(self._parent)
 
-    @_wrapped.setter
-    def _wrapped(self, value):
-        setattr(self._parent, self._name, value)
-
     def __indexSetForIndex(self, index):
         if isinstance(index, slice):
             result = NSMutableIndexSet.alloc().init()
 
             return result
 
-        else:
+        elif isinstance(index, (int, long)):
             if index < 0:
                 v = len(self) + index
                 if v < 0:
             else:
                 return NSIndexSet.alloc().initWithIndex_(index)
 
+        else:
+            raise TypeError(index)
+
 
 
     def __repr__(self):
     def __reduce__(self):
         # Ensure that the proxy itself doesn't get stored
         # in pickles.
-        return _id, self._wrapped
+        return _id, (self._wrapped,)
 
     def __getattr__(self, name):
         # Default: just defer to wrapped list
             raise ValueError("Property '%s' is read-only"%(self._name,))
 
         if isinstance(index, slice):
-            raise ValueError("insert argument 1 is a slice")
+            raise TypeError("insert argument 1 is a slice")
 
         indexes = self.__indexSetForIndex(index)
         self._parent.willChange_valuesAtIndexes_forKey_(
             raise ValueError("Property '%s' is read-only"%(self._name,))
 
         if isinstance(index, slice):
-            raise ValueError("insert argument 1 is a slice")
+            raise TypeError("insert argument 1 is a slice")
 
         indexes = self.__indexSetForIndex(index)
         self._parent.willChange_valuesAtIndexes_forKey_(
                 NSKeyValueChangeInsertion,
                 indexes, self._name)
         try:
-            for item in values:
-                self._wrapped.append(item)
+            self._wrapped.extend(values)
+
         finally:
             self._parent.didChange_valuesAtIndexes_forKey_(
                 NSKeyValueChangeInsertion,
                 indexes, self._name)
 
-    def __iadd__(self, value):
-        return self._wrapped + value
+    def __iadd__(self, values):
+        self.extend(values)
+        return self
 
-# This causes a internal python error:
-#        self._wrapped.extend(value)
-#        return self
+    def __add__(self, values):
+        return self._wrapped + values
+
+    def __mul__(self, count):
+        return self._wrapped * count
 
     def __imul__(self, count):
-        return self._wrapped * count
+        if self._ro:
+            raise ValueError("Property '%s' is read-only"%(self._name,))
+        if not isinstance(count, (int, long)):
+            raise ValueError(count)
 
-# This causes an error I don't quite get yet:
-#        if self._ro:
-#            raise ValueError("Property '%s' is read-only"%(self._name,))
-#        if not isinstance(count, (int, long)):
-#            raise ValueError(count)
-#
-#        indexes = NSIndexSet.alloc().initWithIndexesInRange_((len(self), len(self)*count))
-#        self._parent.willChange_valuesAtIndexes_forKey_(
-#                NSKeyValueChangeInsertion,
-#                indexes, self._name)
-#        try:
-#            self._wrapped *= count
-#        finally:
-#            self._parent.didChange_valuesAtIndexes_forKey_(
-#                NSKeyValueChangeInsertion,
-#                indexes, self._name)
-#
-#        return self
+        indexes = NSIndexSet.alloc().initWithIndexesInRange_((len(self), len(self)*(count-1)))
+        self._parent.willChange_valuesAtIndexes_forKey_(
+                NSKeyValueChangeInsertion,
+                indexes, self._name)
+        try:
+            self._wrapped.__imul__(count)
+        finally:
+            self._parent.didChange_valuesAtIndexes_forKey_(
+                NSKeyValueChangeInsertion,
+                indexes, self._name)
+
+        return self
 
 
     def __eq__(self, other):
 
 
     def __set__(self, object, value):
-        if isinstance(value, array_property):
+        if isinstance(value, array_proxy):
+            if value._name == self._name and value._parent is object:
+                # attr.prop = attr.prop
+                return
+
+        if isinstance(value, array_proxy):
             value = list(value)
 
         super(array_property, self).__set__(object, value)
 
     def __getvalue__(self, object):
         v = object_property.__get__(self, object, None)
-        if v is None:
+        if v is None: 
             v = list()
             object_property.__set__(self, object, v)
         return v
 
     @_wrapped.setter
     def _wrapped(self, value):
-        setattr(self._parent, self._name, value)
+        setattr(self._parent, self._name, value) 
 
     def __getattr__(self, attr):
         return getattr(self._wrapped, attr)
         self._parent.willChangeValueForKey_withSetMutation_usingObjects_(
                 self._name,
                 NSKeyValueMinusSetMutation,
-                set([item])
+                {item}
         )
         try:
             self._wrapped.discard(item)
             self._parent.didChangeValueForKey_withSetMutation_usingObjects_(
                 self._name,
                 NSKeyValueMinusSetMutation,
-                set([item])
+                {item}
             )
 
     def intersection_update(self, other):
         if self._ro:
             raise ValueError("Property '%s' is read-only"%(self._name,))
 
+        other = set(other)
+
         self._parent.willChangeValueForKey_withSetMutation_usingObjects_(
                 self._name,
                 NSKeyValueIntersectSetMutation,
-                set([item])
+                other
         )
         try:
-            self._wrapped.intersection_update(s)
+            self._wrapped.intersection_update(other)
 
         finally:
             self._parent.didChangeValueForKey_withSetMutation_usingObjects_(
                 self._name,
                 NSKeyValueIntersectSetMutation,
-                set([item])
+                other
             )
 
     def pop(self):
         if self._ro:
             raise ValueError("Property '%s' is read-only"%(self._name,))
 
-        return self|other
+        self.update(other)
+        return self
 
     def __isub__(self, other):
         if self._ro:
             raise ValueError("Property '%s' is read-only"%(self._name,))
 
-        return self-other
+        self.difference_update(other)
+        return self
 
     def __ixor__(self, other):
         if self._ro:
             raise ValueError("Property '%s' is read-only"%(self._name,))
 
-        return self^other
+        self.symmetric_difference_update(other)
+        return self
 
     def __iand__(self, other):
         if self._ro:
             raise ValueError("Property '%s' is read-only"%(self._name,))
 
-        return self&other
+        self.intersection_update(other)
+        return self
 
 def makeSetAccessors(name):
     def countOf(self):
             object_property.__set__(self, object, v)
         return set_proxy(self._name, object, self, self._ro)
 
+    def __set__(self, object, value):
+        if isinstance(value, set_proxy):
+            if value._name == self._name and value._parent is object:
+                # attr.prop = attr.prop
+                return
+
+        if isinstance(value, set_proxy):
+            value = list(value)
+
+        super(set_property, self).__set__(object, value)
+
     def __getvalue__(self, object):
         v = object_property.__get__(self, object, None)
         if v is None:

File pyobjc-core/PyObjCTest/test_array_property.py

 from PyObjCTools.TestSupport import *
 import objc
+import pickle
 import collections
+import sys
 
 NSObject = objc.lookUpClass('NSObject')
 NSIndexSet = objc.lookUpClass('NSIndexSet')
 
 class TestArrayPropertyHelper (NSObject):
     array = objc.array_property()
+    array2 = objc.array_property()
     roArray = objc.array_property(read_only=True)
 
 from PyObjCTest.test_object_property import OCObserve
         o = TestArrayPropertyHelper.alloc().init()
         observer.register(o, 'array')
         try:
-            self.assertEqual(len(observer.values), 0)
+            self.assertEqual(observer.seen, {})
             self.assertEqual(len(o.array), 0)
-            self.assertEqual(len(observer.values), 0)
+            self.assertEqual(observer.seen, {'array': []})
             o.array = l
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': l})
 
 
             self.assertEqual(len(o.array), 3)
             self.assertEqual(len(l), 4)
             o.array.append(5)
             self.assertEqual(len(l), 4)
+            self.assertEqual(len(o.array), 4)
 
         finally:
             observer.unregister(o, 'array')
 
+        l = [1,2]
+        o.array2 = l
+        self.assertIsNot(o._array2, l)
+
+        o.array2 = o.array
+        self.assertEqual(o.array2, [1, 2, 3, 5])
+        o.array2.append(1)
+        self.assertEqual(o.array2, [1, 2, 3, 5, 1])
+        self.assertEqual(o.array, [1, 2, 3, 5])
+
+
+        arr = o.array2
+        o._array2 = None
+        self.assertEqual(arr, [])
 
 
     def testGetSetItem(self):
         len(o.array)
         try:
             IS = NSIndexSet.alloc().initWithIndex_(0)
-            self.assertEqual(len(observer.values), 0)
+            self.assertEqual(observer.seen, {'array': []})
 
             o.array.append(1)
 
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': [1]})
             self.assertEqual(observer.values[-1][-1]['indexes'], IS)
             self.assertEqual(observer.values[-1][-1]['new'], [1])
 
+            o.array.append(2)
+            o.array.append(3)
+
 
             self.assertEqual(o.array[0], 1)
             o.array[0] = 4
             self.assertEqual(o.array[0], 4)
-            self.assertEqual(len(observer.values), 2)
+            self.assertEqual(observer.seen, { 'array': [4] })
             self.assertEqual(observer.values[-1][-1]['indexes'], IS)
             self.assertEqual(observer.values[-1][-1]['old'], [1])
             self.assertEqual(observer.values[-1][-1]['new'], [4])
 
+            o.array[-1] = 9
+            self.assertEqual(o.array[2], 9)
+            IS = NSIndexSet.alloc().initWithIndex_(2)
+            self.assertEqual(observer.seen, { 'array': [9] })
+            self.assertEqual(observer.values[-1][-1]['indexes'], IS)
+            self.assertEqual(observer.values[-1][-1]['old'], [3])
+            self.assertEqual(observer.values[-1][-1]['new'], [9])
+
+            self.assertEqual(o.array[-1], 9)
+
         finally:
             observer.unregister(o, 'array')
 
             IS3 = NSMutableIndexSet.alloc().init()
             IS3.addIndex_(0)
             IS3.addIndex_(2)
-            self.assertEqual(len(observer.values), 0)
+            self.assertEqual(observer.seen, {})
 
             o.array = l
 
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': l})
             self.assertNotIn('indexes', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['new'], [1, 2, 3])
 
 
+            o.array[1:3] = [4, 5]
             self.assertEqual(o.array[0], 1)
-            o.array[1:3] = [4, 5]
             self.assertEqual(o.array[1], 4)
             self.assertEqual(o.array[2], 5)
-            self.assertEqual(len(observer.values), 2)
+            self.assertEqual(o.array,[1, 4, 5])
+            self.assertEqual(observer.seen, {'array': [4, 5]})
             self.assertEqual(observer.values[-1][-1]['indexes'], IS2)
             self.assertEqual(observer.values[-1][-1]['old'], [2, 3])
             self.assertEqual(observer.values[-1][-1]['new'], [4, 5])
             self.assertEqual(o.array[0], 9)
             self.assertEqual(o.array[1], 4)
             self.assertEqual(o.array[2], 10)
-            self.assertEqual(len(observer.values), 3)
+            self.assertEqual(observer.seen, { 'array': [9, 10]})
             self.assertEqual(observer.values[-1][-1]['indexes'], IS3)
             self.assertEqual(observer.values[-1][-1]['old'], [1, 5])
             self.assertEqual(observer.values[-1][-1]['new'], [9, 10])
         o = TestArrayPropertyHelper.alloc().init()
         observer.register(o, 'array')
 
+        self.assertEqual(o.array, [])
+
         try:
             IS = NSIndexSet.alloc().initWithIndex_(0)
             IS1 = NSIndexSet.alloc().initWithIndex_(4)
-            self.assertEqual(len(observer.values), 0)
+            self.assertEqual(observer.seen, {'array': []})
 
             o.array = l
 
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': l})
             self.assertNotIn('indexes', observer.values[-1][-1])
 
             self.assertEqual(o.array[0], 1)
             self.assertEqual(o.array[0], 'a')
             self.assertEqual(len(o.array), 4)
 
-            self.assertEqual(len(observer.values), 2)
+            self.assertEqual(observer.seen, {'array': ['a']})
             self.assertEqual(observer.values[-1][-1]['indexes'], IS)
             self.assertNotIn('old', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['new'], ['a'])
             self.assertEqual(o.array[4], 'b')
             self.assertEqual(len(o.array), 5)
 
-            self.assertEqual(len(observer.values), 3)
+            self.assertEqual(observer.seen, {'array': ['b']})
             self.assertEqual(observer.values[-1][-1]['indexes'], IS1)
             self.assertNotIn('old', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['new'], ['b'])
 
+            self.assertRaises(TypeError, o.array.insert, slice(0,2), 4)
+            self.assertRaises(TypeError, o.array.insert, 'a', 4)
+            o.array.insert(0, 'a')
+
         finally:
             observer.unregister(o, 'array')
 
         try:
             IS = NSIndexSet.alloc().initWithIndex_(0)
             IS2 = NSIndexSet.alloc().initWithIndex_(2)
-            self.assertEqual(len(observer.values), 0)
+            self.assertEqual(observer.seen, {})
 
             o.array = l
 
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': l})
             self.assertNotIn('indexes', observer.values[-1][-1])
 
             self.assertEqual(o.array[0], 1)
             self.assertEqual(o.array[0], 2)
             self.assertEqual(len(o.array), 3)
 
-            self.assertEqual(len(observer.values), 2)
             self.assertEqual(observer.values[-1][-1]['indexes'], IS)
             self.assertNotIn('new', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['old'], [1])
             self.assertEqual(v, 4)
             self.assertEqual(len(o.array), 2)
 
-            self.assertEqual(len(observer.values), 3)
             self.assertEqual(observer.values[-1][-1]['indexes'], IS2)
             self.assertNotIn('new', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['old'], [4])
 
+            self.assertRaises(TypeError, o.array.pop, slice(0, 2))
+            self.assertRaises(TypeError, o.array.pop, 'a')
+
         finally:
             observer.unregister(o, 'array')
 
         try:
             IS = NSIndexSet.alloc().initWithIndex_(0)
             IS2 = NSIndexSet.alloc().initWithIndex_(2)
-            self.assertEqual(len(observer.values), 0)
+            self.assertEqual(observer.seen, {})
 
             o.array = l
 
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': l})
             self.assertNotIn('indexes', observer.values[-1][-1])
 
             self.assertEqual(o.array[0], 1)
             self.assertEqual(o.array[0], 2)
             self.assertEqual(len(o.array), 3)
 
-            self.assertEqual(len(observer.values), 2)
             self.assertEqual(observer.values[-1][-1]['indexes'], IS)
             self.assertNotIn('new', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['old'], [1])
             del o.array[2]
             self.assertEqual(len(o.array), 2)
 
-            self.assertEqual(len(observer.values), 3)
             self.assertEqual(observer.values[-1][-1]['indexes'], IS2)
             self.assertNotIn('new', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['old'], [4])
 
             o.array = l
 
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': l})
             self.assertNotIn('indexes', observer.values[-1][-1])
 
             self.assertEqual(o.array[0], 1)
             self.assertEqual(o.array[1], 4)
             self.assertEqual(len(o.array), 2)
 
-            self.assertEqual(len(observer.values), 2)
             self.assertEqual(observer.values[-1][-1]['indexes'], IS)
             self.assertNotIn('new', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['old'], [1, 3])
         try:
             o.array = l
 
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': l })
             self.assertEqual(o.array[0], 1)
 
             o.array.extend(l2)
             self.assertEqual(len(o.array), 7)
             self.assertEqual(o.array[4], 'a')
 
-            self.assertEqual(len(observer.values), 2)
+            self.assertEqual(observer.seen, {'array': l2 })
             self.assertEqual(observer.values[-1][-1]['indexes'], NSIndexSet.alloc().initWithIndexesInRange_((4, 3)))
             self.assertNotIn('old', observer.values[-1][-1])
-            self.assertEqual(observer.values[-1][-1]['new'], ['a', 'b', 'c'])
+            self.assertEqual(observer.values[-1][-1]['new'], l2)
 
         finally:
             observer.unregister(o, 'array')
         try:
             o.array = l
 
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': l})
             self.assertEqual(o.array[0], 1)
 
             o.array += l2
 
+            self.assertEqual(o.array, l + l2)
             self.assertEqual(len(o.array), 7)
             self.assertEqual(o.array[4], 'a')
 
-            #self.assertEqual(len(observer.values), 3)
-            #self.assertEqual(observer.values[-2][-1]['indexes'], NSIndexSet.alloc().initWithIndexesInRange_((4, 3)))
-            #self.assertNotIn('old', observer.values[-2][-1])
-            #self.assertEqual(observer.values[-2][-1]['new'], ['a', 'b', 'c'])
+            self.assertEqual(observer.seen, {'array': l + l2})
+            self.assertEqual(observer.values[-2][-1]['indexes'], NSIndexSet.alloc().initWithIndexesInRange_((4, 3)))
+            self.assertNotIn('old', observer.values[-2][-1])
+            self.assertEqual(observer.values[-2][-1]['new'], l2)
 
-            self.assertEqual(len(observer.values), 2)
             self.assertNotIn('indexes', observer.values[-1][-1])
 
+            before = observer.values[:]
+            v = o.array + l2
+            self.assertEqual(observer.values, before)
+            self.assertEqual(v, l + l2 + l2)
+            self.assertIsInstance(v, list)
+
         finally:
             observer.unregister(o, 'array')
 
+
     def testIMul(self):
         observer = OCObserve.alloc().init()
         l = [1, 2]
         try:
             o.array = l
 
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': l})
             self.assertEqual(o.array[0], 1)
 
+            observer.values[:] = []
             o.array *= 3
 
             self.assertEqual(len(o.array), 6)
             self.assertEqual(o.array[4], 1)
             self.assertEqual(o.array[5], 2)
 
-            #self.assertEqual(len(observer.values), 3)
-            #self.assertEqual(observer.values[-2][-1]['indexes'], NSIndexSet.alloc().initWithIndexesInRange_((2, 4)))
-            #self.assertNotIn('old', observer.values[-2][-1])
-            #self.assertEqual(observer.values[-2][-1]['new'], [1, 2, 1, 2])
+            self.assertEqual(observer.seen, {'array': [ 1, 2, 1, 2, 1, 2]})
+            self.assertEqual(observer.values[-2][-1]['indexes'], NSIndexSet.alloc().initWithIndexesInRange_((2, 4)))
+            self.assertNotIn('old', observer.values[-2][-1])
+            self.assertEqual(observer.values[-2][-1]['new'], [ 1, 2, 1, 2])
 
             self.assertEqual(len(observer.values), 2)
             self.assertNotIn('indexes', observer.values[-1][-1])
 
+            before = observer.values[:]
+            n = o.array * 4
+            self.assertEqual(observer.values, before)
+            self.assertEqual(n, [1,2]* 3 * 4)
+            self.assertIsInstance(n, list)
+
         finally:
             observer.unregister(o, 'array')
 
 
         try:
             IS = NSIndexSet.alloc().initWithIndexesInRange_((0, 4))
-            self.assertEqual(len(observer.values), 0)
+            self.assertEqual(observer.seen, {})
 
             orig_l = l[:]
             o.array = l
 
 
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': l })
             self.assertNotIn('indexes', observer.values[-1][-1])
 
             self.assertEqual(o.array[0], 2)
             self.assertEqual(o.array[3], 4)
             self.assertEqual(len(o.array), 4)
 
-            self.assertEqual(len(observer.values), 2)
+            self.assertEqual(observer.seen, {'array': [1,2,3,4]})
             self.assertEqual(observer.values[-1][-1]['indexes'], IS)
             self.assertEqual(observer.values[-1][-1]['old'], l)
             self.assertEqual(observer.values[-1][-1]['new'], [1,2,3,4])
 
         try:
             IS = NSIndexSet.alloc().initWithIndexesInRange_((0, 4))
-            self.assertEqual(len(observer.values), 0)
+            self.assertEqual(observer.seen, {})
 
             orig_l = l[:]
             o.array = l
 
 
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'array': l })
             self.assertNotIn('indexes', observer.values[-1][-1])
 
             self.assertEqual(o.array[0], 2)
             self.assertEqual(o.array[3], 2)
             self.assertEqual(len(o.array), 4)
 
-            self.assertEqual(len(observer.values), 2)
+            self.assertEqual(observer.seen, {'array': [3, 1, 4, 2]})
             self.assertEqual(observer.values[-1][-1]['indexes'], IS)
             self.assertEqual(observer.values[-1][-1]['old'], l)
             self.assertEqual(observer.values[-1][-1]['new'], [3, 1, 4, 2])
         self.assertRaises(ValueError, o.roArray.extend, [1,2])
         self.assertRaises(ValueError, o.roArray.sort)
         self.assertRaises(ValueError, o.roArray.reverse)
+        self.assertRaises(ValueError, o.roArray.pop)
         try:
             o.roArray[0] = 2
         except ValueError:
         self.assertEqual(len(o.array), 1)
         self.assertEqual(len(array), 1)
 
+    def testPickling(self):
+        o = TestArrayPropertyHelper.alloc().init()
+        o.array.extend([3,4,5])
+
+        self.assertFalse(isinstance(o.array, list))
+
+        p = pickle.dumps(o.array)
+        v = pickle.loads(p)
+        self.assertEqual(v, o.array)
+        self.assertTrue(isinstance(v, list))
+
+    def testRepr(self):
+        o = TestArrayPropertyHelper.alloc().init()
+        o.array.extend([3,4,5])
+
+        self.assertFalse(isinstance(o.array, list))
+
+        self.assertEqual(repr(o.array), '<array proxy for property array %r>'%([3,4,5],))
+
+    def testFinding(self):
+        o = TestArrayPropertyHelper.alloc().init()
+        o.array.extend([3,4,5])
+
+        self.assertEqual(0, o.array.index(3))
+
+    def testCompare(self):
+        o = TestArrayPropertyHelper.alloc().init()
+        o.array.extend([3,4,5])
+        o.array2.extend([4,5])
+
+        self.assertFalse(o.array == o.array2)
+        self.assertFalse(o.array ==  [4,5])
+        self.assertTrue(o.array ==  [3,4,5])
+
+        self.assertTrue(o.array != o.array2)
+        self.assertTrue(o.array !=  [4,5])
+        self.assertFalse(o.array !=  [3,4,5])
+
+        o.array2.insert(0, 3)
+        self.assertFalse(o.array != o.array2)
+        self.assertTrue(o.array == o.array2)
+
+        o.array2 = [4,5]
+        self.assertTrue(o.array < o.array2)
+        self.assertTrue(o.array < [4,5])
+        self.assertFalse(o.array2 < o.array)
+        self.assertFalse(o.array2 < [4,5])
+        self.assertTrue(o.array2 <= o.array2)
+        self.assertTrue(o.array2 <= [4,5])
+
+        self.assertTrue(o.array <= o.array2)
+        self.assertTrue(o.array <= [4,5])
+        self.assertFalse(o.array2 <= o.array)
+
+        self.assertFalse(o.array > o.array2)
+        self.assertFalse(o.array > [4,5])
+        self.assertTrue(o.array2 > o.array)
+        self.assertFalse(o.array2 > [4,5])
+
+        self.assertFalse(o.array >= o.array2)
+        self.assertFalse(o.array >= [4,5])
+        self.assertTrue(o.array2 >= o.array)
+        self.assertTrue(o.array2 >= [4,5])
+        self.assertTrue(o.array2 >= o.array2)
+
+        if sys.version_info[0] == 2:
+            n = cmp(o.array2, o.array)
+            self.assertEqual(n, 1)
+
+            n = cmp(o.array2, [3,4,5])
+            self.assertEqual(n, 1)
+
+
+        
+
+
 if __name__ == "__main__":
     main()

File pyobjc-core/PyObjCTest/test_dict_property.py

 
         o = TestDictPropertyHelper.alloc().init()
         observer.register(o, 'aDict')
+
+        cleanup = []
         try:
             self.assertEqual(len(o.aDict), 0)
             self.assertEqual(o.aDict, {})
-            self.assertEqual(len(observer.values), 0)
+
+            seen = { v[1]: v[2]['new'] for v in observer.values }
+            self.assertEqual(seen, {'aDict': {}})
 
             o.aDict['key'] = 42
-            self.assertEqual(len(observer.values), 0)
+            seen = { v[1]: v[2]['new'] for v in observer.values }
+            self.assertEqual(seen, {'aDict': { 'key': 42}})
 
             observer.register(o, 'aDict.key')
+            cleanup.append(lambda: observer.unregister(o, 'aDict.key'))
 
             o.aDict['key'] = 43
-            self.assertEqual(len(observer.values), 1)
+            seen = { v[1]: v[2]['new'] for v in observer.values }
+            self.assertEqual(seen, {'aDict': { 'key': 43}, 'aDict.key': 43})
 
             self.assertNotIn('indexes', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['old'], 42)
 
             del o.aDict['key']
 
-            self.assertEqual(len(observer.values), 2)
+            seen = { v[1]: v[2]['new'] for v in observer.values }
+            self.assertEqual(seen, {'aDict': {}, 'aDict.key': None})
             self.assertNotIn('indexes', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['old'], 43)
             self.assertEqual(observer.values[-1][-1]['new'], None)
 
         finally:
             observer.unregister(o, 'aDict')
-            observer.unregister(o, 'aDict.key')
+            for func in cleanup[::-1]:
+                func()
 
 if __name__ == "__main__":
     main()

File pyobjc-core/PyObjCTest/test_object_property.py

 from __future__ import unicode_literals
 from PyObjCTools.TestSupport import *
 import objc
+import copy
 from PyObjCTest.fnd import *
 
 objc.registerMetaDataForSelector(
         self.registrations = []
         return self
 
+    @property
+    def seen(self):
+        return { v[1]: v[2]['new'] for v in self.values }
+
+
     def register(self, object, keypath):
         object.addObserver_forKeyPath_options_context_(
                 self, keypath, 0x3, None)
 
         # We don't get to keep the 'change' dictionary, make
         # a copy (it gets reused in future calls)
-        self.values.append((object, keypath, dict(change)))
+        new_change = {}
+        for k in change:
+            v = change[k]
+            if isinstance(v, (list, tuple, set)):
+                v = copy.copy(v)
+            new_change[k] = v
+        self.values.append((object, keypath, new_change))
 
     def __enter__(self):
         return self
             self.assertEqual(object2.pyobjc_instanceMethods.p3(), ("c", "b", "a"))
             self.assertEqual(object2.pyobjc_instanceMethods.p4(), "c")
 
-            seen = { v[1]: v[2]['new'] for v in observer1.values }
-            self.assertEqual(seen,
+            #seen = { v[1]: v[2]['new'] for v in observer1.values }
+            self.assertEqual(observer1.seen,
                 {'p1': 'a', 'p2': 'b', 'p3': ('a', 'b') })
 
-            seen = { v[1]: v[2]['new'] for v in observer2.values }
-            self.assertEqual(seen,
+            #seen = { v[1]: v[2]['new'] for v in observer2.values }
+            self.assertEqual(observer2.seen,
                 {'p1': 'a', 'p2': 'b', 'p3': ('c', 'b', 'a'), 'p4': 'c', 'p5': '-c-' })
 
         finally:
             self.assertEqual(object2.pyobjc_instanceMethods.p3(), ("c", "b", "a"))
             self.assertEqual(object2.pyobjc_instanceMethods.p4(), "c")
 
-            seen = { v[1]: v[2]['new'] for v in observer1.values }
-            self.assertEqual(seen,
+            #seen = { v[1]: v[2]['new'] for v in observer1.values }
+            self.assertEqual(observer1.seen,
                 {'p1': 'a', 'p2': 'b', 'p3': ('a', 'b') })
 
-            seen = { v[1]: v[2]['new'] for v in observer2.values }
-            self.assertEqual(seen,
+            #seen = { v[1]: v[2]['new'] for v in observer2.values }
+            self.assertEqual(observer2.seen,
                {'p1': 'a', 'p2': 'b', 'p3': ('c', 'b', 'a'), 'p4': 'c' })
 
         finally:
                 else:
                     return (False, 2, "snake")
 
+        class OCTestObjectProperty4b (OCTestObjectProperty4):
+            @OCTestObjectProperty4.p1.validate
+            def p1(self, value, error):
+                if value == 2:
+                    return (True, value, None)
+                else:
+                    return (False, 2, "monty")
+
 
         o = OCTestObjectProperty4.alloc().init()
         o.p1 = 'f'
         self.assertEqual(value, 2)
         self.assertEqual(error, "snake")
 
+        l = []
+        o = OCTestObjectProperty4b.alloc().init()
+        o.p1 = 'f'
+        self.assertEqual(o.p1, 'f?!')
+        self.assertEqual(o._p1, 'f?')
+        self.assertEqual(l, [('set', 'f'), ('get',)])
+
+        ok, value, error = o.validateValue_forKey_error_(
+                2, 'p1', None)
+        self.assertTrue(ok)
+        self.assertEqual(value, 2)
+        self.assertEqual(error, None)
+
+        ok, value, error = o.validateValue_forKey_error_(
+                9, 'p1', None)
+        self.assertFalse(ok)
+        self.assertEqual(value, 2)
+        self.assertEqual(error, "monty")
+
     def testNative(self):
         l = []
         class OCTestObjectProperty7 (NSObject):
         else:
             self.fail("ValueError not raised")
 
+class TestBoolProperty (TestCase):
+    def testDefault(self):
+        class OCTestBoolProperty1 (NSObject):
+            p1 = objc.bool_property()
+
+        o = OCTestBoolProperty1.alloc().init()
+        self.assertEqual(o.p1, False)
+
+        o.p1 = [1, 2]
+        self.assertEqual(o.p1, True)
+
 if __name__ == "__main__":
     main()

File pyobjc-core/PyObjCTest/test_set_property.py

         self.assertEqual(len(o.aSet), 2)
         self.assertEqual(len(aSet), 3)
 
+    def testRepr(self):
+        o = TestSetPropertyHelper.alloc().init()
+        aSet = set([1,2])
+        o.aSet = aSet
+
+        self.assertEqual(repr(o.aSet), '<set proxy for property aSet %r>'%(aSet,))
+
     def testDefault(self):
         with OCObserve.alloc().init() as observer:
             o = TestSetPropertyHelper.alloc().init()
             observer.register(o, 'aSet')
 
             o.aSet = set()
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'aSet': set()})
+
 
             self.assertEqual(len(o.aSet), 0)
             o.aSet.add('a')
             o.aSet.add('b')
             self.assertEqual(len(o.aSet), 2)
-            self.assertEqual(len(observer.values), 3)
+            self.assertEqual(observer.seen, {'aSet': {'b'}})
 
             self.assertEqual(observer.values[-2][-1]['kind'], 2)
             self.assertNotIn('old', observer.values[-2][-1])
             self.assertEqual(len(o.aSet), 0)
             self.assertEqual(len(proxy), 0)
 
-            self.assertEqual(len(observer.values), 4)
             self.assertEqual(observer.values[-1][-1]['old'], set(['a', 'b']))
             self.assertNotIn('new', observer.values[-1][-1])
 
         with OCObserve.alloc().init() as observer:
             o = TestSetPropertyHelper.alloc().init()
             observer.register(o, 'aSet')
+            self.assertEqual(o.aSet, set())
+            self.assertEqual(len(observer.values), 1)
 
             o.aSet.update([1,2,3])
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(len(observer.values), 2)
             self.assertEqual(observer.values[-1][-1]['kind'], 2)
             self.assertNotIn('old', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['new'], set([1, 2, 3]))
 
             o.aSet.update(set([3,4,5]))
-            self.assertEqual(len(observer.values), 2)
+            self.assertEqual(len(observer.values), 3)
             self.assertEqual(observer.values[-1][-1]['kind'], 2)
             self.assertNotIn('old', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['new'], set([4, 5]))
             observer.register(o, 'aSet')
 
             o.aSet.add(1)
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'aSet': {1}})
             self.assertNotIn('old', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['new'], set([1]))
 
             o.aSet.discard(1)
-            self.assertEqual(len(observer.values), 2)
             self.assertNotIn('new', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['old'], set([1]))
 
             o.aSet.discard(2)
-            self.assertEqual(len(observer.values), 3)
             self.assertNotIn('new', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['old'], set([]))
 
             observer.register(o, 'aSet')
 
             o.aSet.add(1)
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(observer.seen, {'aSet': {1}})
             self.assertNotIn('old', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['new'], set([1]))
 
             o.aSet.remove(1)
-            self.assertEqual(len(observer.values), 2)
             self.assertNotIn('new', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['old'], set([1]))
 
             self.assertRaises(KeyError, o.aSet.remove, 2)
-            self.assertEqual(len(observer.values), 3)
             self.assertNotIn('new', observer.values[-1][-1])
             self.assertEqual(observer.values[-1][-1]['old'], set([]))
 
             # "o.aSet |= value" is actually  "o.aSet = o.aSet | value" and
             # we get the some KVO notificatons as when a new value is set.
 
+            self.assertEqual(o.aSet, {1})
             o.aSet |= set([2,3])
+            self.assertEqual(o.aSet, {1,2,3})
             self.assertEqual(o.aSet, set([1,2,3]))
-            self.assertEqual(len(observer.values), 1)
+            self.assertEqual(len(observer.values), 2)
+            print observer.values[-1][-1]
             self.assertEqual(observer.values[-1][-1]['kind'], 1)
-            self.assertEqual(observer.values[-1][-1]['old'], set([1]))
+            #self.assertEqual(observer.values[-1][-1]['old'], set([1]))
             self.assertEqual(observer.values[-1][-1]['new'], set([1,2,3]))
 
+            self.assertEqual(o.aSet, {1,2,3})
             o.aSet &= set([3, 4])
+            self.assertEqual(o.aSet, {3})
             self.assertEqual(o.aSet, set([3]))
-            self.assertEqual(len(observer.values), 2)
+            self.assertEqual(len(observer.values), 4)
             self.assertEqual(observer.values[-1][-1]['kind'], 1)
+            print observer.values[-1][-1]
+            print id(observer.values[-1][-1]['old'])
+            print id(observer.values[-1][-1]['new'])
             self.assertEqual(observer.values[-1][-1]['old'], set([1,2,3]))
             self.assertEqual(observer.values[-1][-1]['new'], set([3]))
 
+            self.assertEqual(o.aSet, {3})
             o.aSet -= set([3])
+            self.assertEqual(o.aSet, {})
             self.assertEqual(o.aSet, set([]))
-            self.assertEqual(len(observer.values), 3)
+            self.assertEqual(len(observer.values), 4)
             self.assertEqual(observer.values[-1][-1]['kind'], 1)
             self.assertEqual(observer.values[-1][-1]['old'], set([3]))
             self.assertEqual(observer.values[-1][-1]['new'], set())
 
             o.aSet = set([1,2,3])
-            self.assertEqual(len(observer.values), 4)
+            self.assertEqual(len(observer.values), 5)
 
+            self.assertEqual(o.aSet, {1,2,3})
             o.aSet ^= set([1, 4])
-            self.assertEqual(o.aSet, set([2, 3, 4]))
-            self.assertEqual(len(observer.values), 5)
+            self.assertEqual(o.aSet, {2, 3, 4})
+            self.assertEqual(len(observer.values), 6)
             self.assertEqual(observer.values[-1][-1]['kind'], 1)
             self.assertEqual(observer.values[-1][-1]['old'], set([1,2,3]))
             self.assertEqual(observer.values[-1][-1]['new'], set([2,3,4]))