[PyObjC-svn] r2497 - in trunk/pyobjc/pyobjc-core: Lib/objc PyObjCTest
[email protected] Tue, 29 Jun 2010 05:41:59 -0500
| Newsgroups | gmane.comp.python.pyobjc.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: ronaldoussoren
Date: Tue Jun 29 05:41:58 2010
New Revision: 2497
Log:
Actually implement tests for objc.array_property and
fix issues that cropped up.
Modified:
trunk/pyobjc/pyobjc-core/Lib/objc/_properties.py
trunk/pyobjc/pyobjc-core/PyObjCTest/test_array_property.py
Modified: trunk/pyobjc/pyobjc-core/Lib/objc/_properties.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/Lib/objc/_properties.py (original)
+++ trunk/pyobjc/pyobjc-core/Lib/objc/_properties.py Tue Jun 29 05:41:58 2010
@@ -1,16 +1,23 @@
__all__ = ('object_property', 'bool_property',
'array_property', 'set_property', 'dict_property')
-from objc import ivar, selector, _C_ID, _C_NSBOOL, _C_BOOL, NULL
+from objc import ivar, selector, _C_ID, _C_NSBOOL, _C_BOOL, NULL, _C_NSUInteger
from objc import lookUpClass
+import collections
+from copy import copy as copy_func
+import sys
NSSet = lookUpClass('NSSet')
+NSObject = lookUpClass('NSObject')
def attrsetter(prop, name, copy):
if copy:
def func(self, value):
- setattr(self, name, value.copy())
+ if isinstance(value, NSObject):
+ setattr(self, name, value.copy())
+ else:
+ setattr(self, name, copy_func(value))
else:
def func(self, value):
setattr(self, name, value)
@@ -268,18 +275,17 @@
NSKeyValueChangeRemoval = 3
NSKeyValueChangeReplacement = 4
-
-class array_proxy (object):
+# FIXME: split into two: array_proxy and mutable_array_proxy
+class array_proxy (collections.MutableSequence):
# XXX: The implemenation should be complete, but is currently not
# tested.
__slots__ = ('_name', '_wrapped', '_parent', '_ro')
- def __init__(cls, name, parent, wrapped, read_only):
- v = cls.alloc().init()
- v._name = name
- v._wrapped = wrapped
- v._parent = parent
- v._ro = read_only
+ def __init__(self, name, parent, wrapped, read_only):
+ self._wrapped = wrapped
+ self._name = name
+ self._parent = parent
+ self._ro = read_only
def __indexSetForIndex(self, index):
@@ -287,7 +293,7 @@
result = NSMutableIndexSet.alloc().init()
start, stop, step = index.indices(len(self._wrapped))
for i in xrange(start, stop, step):
- result.addIndex(index)
+ result.addIndex_(i)
return result
@@ -299,7 +305,7 @@
return NSIndexSet.alloc().initWithIndex_(v)
else:
- return NSIndexSet.alloc().initWithIndex_(v)
+ return NSIndexSet.alloc().initWithIndex_(index)
@@ -315,12 +321,15 @@
# Default: just defer to wrapped list
return getattr(self._wrapped, name)
+ def __len__(self):
+ return self._wrapped.__len__()
+
def __getitem__(self, index):
return self._wrapped[index]
def __setitem__(self, index, value):
if self._ro:
- raise TypeError("Property '%s' is read-only"%(self._name,))
+ raise ValueError("Property '%s' is read-only"%(self._name,))
indexes = self.__indexSetForIndex(index)
self._parent.willChange_valuesAtIndexes_forKey_(
@@ -335,14 +344,14 @@
def __delitem__(self, index):
if self._ro:
- raise TypeError("Property '%s' is read-only"%(self._name,))
+ raise ValueError("Property '%s' is read-only"%(self._name,))
indexes = self.__indexSetForIndex(index)
self._parent.willChange_valuesAtIndexes_forKey_(
NSKeyValueChangeRemoval,
indexes, self._name)
try:
- self._wrapped[index] = value
+ del self._wrapped[index]
finally:
self._parent.didChange_valuesAtIndexes_forKey_(
NSKeyValueChangeRemoval,
@@ -350,9 +359,9 @@
def append(self, value):
if self._ro:
- raise TypeError("Property '%s' is read-only"%(self._name,))
+ raise ValueError("Property '%s' is read-only"%(self._name,))
- index = len(self._wrapped)
+ index = len(self)
indexes = NSIndexSet.alloc().initWithIndex_(index)
self._parent.willChange_valuesAtIndexes_forKey_(
NSKeyValueChangeInsertion,
@@ -365,8 +374,11 @@
indexes, self._name)
def insert(self, index, value):
+ if self._ro:
+ raise ValueError("Property '%s' is read-only"%(self._name,))
+
if isinstance(index, slice):
- raise TypeError("insert argument 1 is a slice")
+ raise ValueError("insert argument 1 is a slice")
indexes = self.__indexSetForIndex(index)
self._parent.willChange_valuesAtIndexes_forKey_(
@@ -381,17 +393,17 @@
def pop(self, index=-1):
if self._ro:
- raise TypeError("Property '%s' is read-only"%(self._name,))
+ raise ValueError("Property '%s' is read-only"%(self._name,))
if isinstance(index, slice):
- raise TypeError("insert argument 1 is a slice")
+ raise ValueError("insert argument 1 is a slice")
indexes = self.__indexSetForIndex(index)
self._parent.willChange_valuesAtIndexes_forKey_(
NSKeyValueChangeRemoval,
indexes, self._name)
try:
- self._wrapped.insert(index, value)
+ return self._wrapped.pop(index)
finally:
self._parent.didChange_valuesAtIndexes_forKey_(
NSKeyValueChangeRemoval,
@@ -399,13 +411,102 @@
def extend(self, values):
# XXX: This is suboptimal but correct
- for item in values:
- self.append(values)
+ if self._ro:
+ raise ValueError("Property '%s' is read-only"%(self._name,))
+
+ values = list(values)
+
+ indexes = NSIndexSet.alloc().initWithIndexesInRange_((len(self), len(values)))
+
+ self._parent.willChange_valuesAtIndexes_forKey_(
+ NSKeyValueChangeInsertion,
+ indexes, self._name)
+ try:
+ for item in values:
+ self._wrapped.append(item)
+ finally:
+ self._parent.didChange_valuesAtIndexes_forKey_(
+ NSKeyValueChangeInsertion,
+ indexes, self._name)
+
+ def __iadd__(self, value):
+ self._wrapped.extend(value)
+ return self
+
+ def __imul__(self, count):
+ 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
+
+
+ def __eq__(self, other):
+ if isinstance(other, array_proxy):
+ return self._wrapped == other._wrapped
+ else:
+ return self._wrapped == other
+
+ def __ne__(self, other):
+ if isinstance(other, array_proxy):
+ return self._wrapped != other._wrapped
+
+ else:
+ return self._wrapped != other
+
+ def __lt__(self, other):
+ if isinstance(other, array_proxy):
+ return self._wrapped < other._wrapped
+
+ else:
+ return self._wrapped < other
+
+ def __le__(self, other):
+ if isinstance(other, array_proxy):
+ return self._wrapped <= other._wrapped
+
+ else:
+ return self._wrapped <= other
+
+ def __gt__(self, other):
+ if isinstance(other, array_proxy):
+ return self._wrapped > other._wrapped
+
+ else:
+ return self._wrapped > other
+
+ def __ge__(self, other):
+ if isinstance(other, array_proxy):
+ return self._wrapped >= other._wrapped
+
+ else:
+ return self._wrapped >= other
+
+
+ if sys.version_info[0] == 2:
+ def __cmp__(self, other):
+ if isinstance(other, array_proxy):
+ return cmp(self._wrapped, other._wrapped)
+
+ else:
+ return cmp(self._wrapped, other)
def sort(self, cmp=None, key=None, reverse=False):
if self._ro:
- raise TypeError("Property '%s' is read-only"%(self._name,))
+ raise ValueError("Property '%s' is read-only"%(self._name,))
indexes = NSIndexSet.alloc().initWithIndexesInRange_(
(0, len(self._wrapped)))
@@ -421,7 +522,7 @@
def reverse(self):
if self._ro:
- raise TypeError("Property '%s' is read-only"%(self._name,))
+ raise ValueError("Property '%s' is read-only"%(self._name,))
indexes = NSIndexSet.alloc().initWithIndexesInRange_(
(0, len(self._wrapped)))
@@ -435,14 +536,96 @@
NSKeyValueChangeReplacement,
indexes, self._name)
+def makeArrayAccessors(name):
+
+ def countOf(self):
+ return len(getattr(self, name))
+
+ def objectIn(self, idx):
+ return getattr(self, name)[idx]
+
+ def insert(self, value, idx):
+ getattr(self, name).insert(idx, value)
+
+ def replace(self, idx, value):
+ getattr(self, name)[idx] = value
+
+ def remove(self, idx):
+ del getattr(self, name)[idx]
+
+ return countOf, objectIn, insert, remove, replace
class array_property (object_property):
- def __get__(self):
- v = object_property.__get__(self)
+ def __init__(self, name=None,
+ read_only=False, copy=True, dynamic=False,
+ ivar=None, depends_on=None):
+ super(array_property, self).__init__(name,
+ read_only=read_only,
+ copy=copy, dynamic=dynamic,
+ ivar=ivar, depends_on=depends_on)
+
+ def __pyobjc_class_setup__(self, name, class_dict, instance_methods, class_methods):
+ super(array_property, self).__pyobjc_class_setup__(name, class_dict, instance_methods, class_methods)
+
+
+ # Insert (Mutable) Indexed Accessors
+ # FIXME: should only do the mutable bits when we're actually a mutable property
+
+ name = self._name
+ Name = name[0].upper() + name[1:]
+
+ countOf, objectIn, insert, remove, replace = makeArrayAccessors(self._name)
+
+ countOf = selector(countOf,
+ selector = 'countOf%s'%(Name,),
+ signature = _C_NSUInteger + '@:',
+ )
+ countOf.isHidden = True
+ instance_methods.add(countOf)
+
+ objectIn = selector(objectIn,
+ selector = 'objectIn%sAtIndex:'%(Name,),
+ signature = '@@:' + _C_NSUInteger,
+ )
+ objectIn.isHidden = True
+ instance_methods.add(objectIn)
+
+ insert = selector(insert,
+ selector = 'insertObject:in%sAtIndex:'%(Name,),
+ signature = 'v@:@' + _C_NSUInteger,
+ )
+ insert.isHidden = True
+ instance_methods.add(insert)
+
+ remove = selector(remove,
+ selector = 'removeObjectFrom%sAtIndex:'%(Name,),
+ signature = 'v@:' + _C_NSUInteger,
+ )
+ remove.isHidden = True
+ instance_methods.add(remove)
+
+ replace = selector(replace,
+ selector = 'replaceObjectIn%sAtIndex:withObject:'%(Name,),
+ signature = 'v@:' + _C_NSUInteger + '@',
+ )
+ replace.isHidden = True
+ instance_methods.add(replace)
+
+
+ def __set__(self, object, value):
+ if isinstance(value, array_property):
+ print "set1", object, value
+ value = list(value)
+ print "set2", object, value
+
+ super(array_property, self).__set__(object, value)
+
+ def __get__(self, object, owner):
+ v = object_property.__get__(self, object, owner)
if v is None:
v = list()
- object_property.__set__(self, v)
- return array_proxy(self._name, self, v, self._ro)
+ object_property.__set__(self, object, v)
+ return array_proxy(self._name, object, v, self._ro)
NSKeyValueUnionSetMutation = 1,
NSKeyValueMinusSetMutation = 2,
Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_array_property.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_array_property.py (original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_array_property.py Tue Jun 29 05:41:58 2010
@@ -1,83 +1,588 @@
from PyObjCTools.TestSupport import *
+import objc
+import collections
+NSObject = objc.lookUpClass('NSObject')
+NSIndexSet = objc.lookUpClass('NSIndexSet')
+NSMutableIndexSet = objc.lookUpClass('NSMutableIndexSet')
+
+class TestArrayPropertyHelper (NSObject):
+ array = objc.array_property()
+ roArray = objc.array_property(read_only=True)
+
+from test_object_property import OCObserve
class TestArrayProperty (TestCase):
- def testMissing(self):
+ def _testMissing(self):
self.fail("Implement tests")
def testGetting(self):
# Check that default value is an empty value
# Check that value is a proxy object
- self.fail("todo")
+ o = TestArrayPropertyHelper.alloc().init()
+
+ v = o.array
+ self.failUnlessIsInstance(v, collections.MutableSequence)
+
+ self.failUnlessEqual(len(v), 0)
+
+ v.append(1)
+ self.failUnlessEqual(len(v), 1)
+
+ self.assertEquals(type(v).__name__, 'array_proxy')
def testSetting(self):
# Set value, check that
# (1) value gets copied
# (2) accessing the property result in proxy
- self.fail("todo")
+ observer = OCObserve.alloc().init()
+ l = [1, 2, 3]
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+ try:
+ self.assertEquals(len(observer.values), 0)
+ self.assertEquals(len(o.array), 0)
+ self.assertEquals(len(observer.values), 0)
+ o.array = l
+ self.assertEquals(len(observer.values), 1)
+
+
+ self.assertEquals(len(o.array), 3)
+
+ # This shouldn't affect the property
+ l.append(4)
+ self.assertEquals(len(o.array), 3)
+
+ self.assertEquals(len(l), 4)
+ o.array.append(5)
+ self.assertEquals(len(l), 4)
+
+ finally:
+ observer.unregister(o, 'array')
+
+
def testGetSetItem(self):
# Use __getitem__, __setitem__ interface and check
# that the correct KVO events get emitted.
- self.fail("todo")
+ observer = OCObserve.alloc().init()
+ l = [1, 2, 3]
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+
+ # FIXME: the call to len shouldn't be necessary
+ len(o.array)
+ try:
+ IS = NSIndexSet.alloc().initWithIndex_(0)
+ self.assertEquals(len(observer.values), 0)
+
+ o.array.append(1)
+
+ self.assertEquals(len(observer.values), 1)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS)
+ self.assertEquals(observer.values[-1][-1]['new'], [1])
+
+
+ self.assertEquals(o.array[0], 1)
+ o.array[0] = 4
+ self.assertEquals(o.array[0], 4)
+ self.assertEquals(len(observer.values), 2)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS)
+ self.assertEquals(observer.values[-1][-1]['old'], [1])
+ self.assertEquals(observer.values[-1][-1]['new'], [4])
+
+ finally:
+ observer.unregister(o, 'array')
def testGetSetSlice(self):
# Same as testGetSetItem, but using slice
- self.fail("todo")
+ observer = OCObserve.alloc().init()
+ l = [1, 2, 3]
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+
+ try:
+ IS = NSIndexSet.alloc().initWithIndexesInRange_((0, 3))
+ IS2 = NSIndexSet.alloc().initWithIndexesInRange_((1, 2))
+ IS3 = NSMutableIndexSet.alloc().init()
+ IS3.addIndex_(0)
+ IS3.addIndex_(2)
+ self.assertEquals(len(observer.values), 0)
+
+ o.array = l
+
+ self.assertEquals(len(observer.values), 1)
+ self.assertNotIn('indexes', observer.values[-1][-1])
+ self.assertEquals(observer.values[-1][-1]['new'], [1, 2, 3])
+
+
+ self.assertEquals(o.array[0], 1)
+ o.array[1:3] = [4, 5]
+ self.assertEquals(o.array[1], 4)
+ self.assertEquals(o.array[2], 5)
+ self.assertEquals(len(observer.values), 2)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS2)
+ self.assertEquals(observer.values[-1][-1]['old'], [2, 3])
+ self.assertEquals(observer.values[-1][-1]['new'], [4, 5])
+
+ self.assertEquals(o.array[0], 1)
+ o.array[0:3:2] = [9, 10]
+ self.assertEquals(o.array[0], 9)
+ self.assertEquals(o.array[1], 4)
+ self.assertEquals(o.array[2], 10)
+ self.assertEquals(len(observer.values), 3)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS3)
+ self.assertEquals(observer.values[-1][-1]['old'], [1, 5])
+ self.assertEquals(observer.values[-1][-1]['new'], [9, 10])
+
+ finally:
+ observer.unregister(o, 'array')
def testInsert(self):
# Use insert method and check that the correct
# KVO events get emitted
- self.fail("todo")
+ # Same as testGetSetItem, but using slice
+ observer = OCObserve.alloc().init()
+ l = [1, 2, 3]
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+
+ try:
+ IS = NSIndexSet.alloc().initWithIndex_(0)
+ IS1 = NSIndexSet.alloc().initWithIndex_(4)
+ self.assertEquals(len(observer.values), 0)
+
+ o.array = l
+
+ self.assertEquals(len(observer.values), 1)
+ self.assertNotIn('indexes', observer.values[-1][-1])
+
+ self.assertEquals(o.array[0], 1)
+
+
+ o.array.insert(0, 'a')
+ self.assertEquals(o.array[0], 'a')
+ self.assertEquals(len(o.array), 4)
+
+ self.assertEquals(len(observer.values), 2)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS)
+ self.assertNotIn('old', observer.values[-1][-1])
+ self.assertEquals(observer.values[-1][-1]['new'], ['a'])
+
+ o.array.insert(4, 'b')
+ self.assertEquals(o.array[4], 'b')
+ self.assertEquals(len(o.array), 5)
+
+ self.assertEquals(len(observer.values), 3)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS1)
+ self.assertNotIn('old', observer.values[-1][-1])
+ self.assertEquals(observer.values[-1][-1]['new'], ['b'])
+
+ finally:
+ observer.unregister(o, 'array')
def testPop(self):
# Use pop method and check that the correct
# KVO events get emitted
- self.fail("todo")
+ observer = OCObserve.alloc().init()
+ l = [1, 2, 3, 4]
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+
+ try:
+ IS = NSIndexSet.alloc().initWithIndex_(0)
+ IS2 = NSIndexSet.alloc().initWithIndex_(2)
+ self.assertEquals(len(observer.values), 0)
+
+ o.array = l
+
+ self.assertEquals(len(observer.values), 1)
+ self.assertNotIn('indexes', observer.values[-1][-1])
+
+ self.assertEquals(o.array[0], 1)
+
+
+ v = o.array.pop(0)
+ self.assertEquals(v, 1)
+ self.assertEquals(o.array[0], 2)
+ self.assertEquals(len(o.array), 3)
+
+ self.assertEquals(len(observer.values), 2)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS)
+ self.assertNotIn('new', observer.values[-1][-1])
+ self.assertEquals(observer.values[-1][-1]['old'], [1])
+
+ v = o.array.pop(2)
+ self.assertEquals(v, 4)
+ self.assertEquals(len(o.array), 2)
+
+ self.assertEquals(len(observer.values), 3)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS2)
+ self.assertNotIn('new', observer.values[-1][-1])
+ self.assertEquals(observer.values[-1][-1]['old'], [4])
+
+ finally:
+ observer.unregister(o, 'array')
def testDelItem(self):
# Use __delitem__and check that the correct
# KVO events get emitted
- self.fail("todo")
+ observer = OCObserve.alloc().init()
+ l = [1, 2, 3, 4]
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+
+ try:
+ IS = NSIndexSet.alloc().initWithIndex_(0)
+ IS2 = NSIndexSet.alloc().initWithIndex_(2)
+ self.assertEquals(len(observer.values), 0)
+
+ o.array = l
+
+ self.assertEquals(len(observer.values), 1)
+ self.assertNotIn('indexes', observer.values[-1][-1])
+
+ self.assertEquals(o.array[0], 1)
+
+
+ del o.array[0]
+ self.assertEquals(o.array[0], 2)
+ self.assertEquals(len(o.array), 3)
+
+ self.assertEquals(len(observer.values), 2)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS)
+ self.assertNotIn('new', observer.values[-1][-1])
+ self.assertEquals(observer.values[-1][-1]['old'], [1])
+
+ del o.array[2]
+ self.assertEquals(len(o.array), 2)
+
+ self.assertEquals(len(observer.values), 3)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS2)
+ self.assertNotIn('new', observer.values[-1][-1])
+ self.assertEquals(observer.values[-1][-1]['old'], [4])
+
+ finally:
+ observer.unregister(o, 'array')
def testDelSlice(self):
# As testDelItem, but using slices
- self.fail("todo")
+ observer = OCObserve.alloc().init()
+ l = [1, 2, 3, 4]
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+
+ try:
+ IS = NSMutableIndexSet.alloc().init()
+ IS.addIndex_(0)
+ IS.addIndex_(2)
+ self.assertEquals(len(observer.values), 0)
+
+ o.array = l
+
+ self.assertEquals(len(observer.values), 1)
+ self.assertNotIn('indexes', observer.values[-1][-1])
+
+ self.assertEquals(o.array[0], 1)
+
+
+ del o.array[0:4:2]
+ self.assertEquals(o.array[0], 2)
+ self.assertEquals(o.array[1], 4)
+ self.assertEquals(len(o.array), 2)
+
+ self.assertEquals(len(observer.values), 2)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS)
+ self.assertNotIn('new', observer.values[-1][-1])
+ self.assertEquals(observer.values[-1][-1]['old'], [1, 3])
+
+ finally:
+ observer.unregister(o, 'array')
+
+ def testExtend(self):
+ observer = OCObserve.alloc().init()
+ l = [1, 2, 3, 4]
+ l2 = ['a', 'b', 'c']
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+
+ try:
+ o.array = l
+
+ self.assertEquals(len(observer.values), 1)
+ self.assertEquals(o.array[0], 1)
+
+ o.array.extend(l2)
+
+ self.assertEquals(len(o.array), 7)
+ self.assertEquals(o.array[4], 'a')
+
+ self.assertEquals(len(observer.values), 2)
+ self.assertEquals(observer.values[-1][-1]['indexes'], NSIndexSet.alloc().initWithIndexesInRange_((4, 3)))
+ self.assertNotIn('old', observer.values[-1][-1])
+ self.assertEquals(observer.values[-1][-1]['new'], ['a', 'b', 'c'])
+
+ finally:
+ observer.unregister(o, 'array')
+
+ def testIAdd(self):
+ observer = OCObserve.alloc().init()
+ l = [1, 2, 3, 4]
+ l2 = ['a', 'b', 'c']
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+
+ try:
+ o.array = l
+
+ self.assertEquals(len(observer.values), 1)
+ self.assertEquals(o.array[0], 1)
+
+ o.array += l2
+
+ self.assertEquals(len(o.array), 7)
+ self.assertEquals(o.array[4], 'a')
+
+ self.assertEquals(len(observer.values), 3)
+ self.assertEquals(observer.values[-2][-1]['indexes'], NSIndexSet.alloc().initWithIndexesInRange_((4, 3)))
+ self.assertNotIn('old', observer.values[-2][-1])
+ self.assertEquals(observer.values[-2][-1]['new'], ['a', 'b', 'c'])
+
+ self.assertNotIn('indexes', observer.values[-1][-1])
+
+ finally:
+ observer.unregister(o, 'array')
+
+ def testIMul(self):
+ observer = OCObserve.alloc().init()
+ l = [1, 2]
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+
+ try:
+ o.array = l
+
+ self.assertEquals(len(observer.values), 1)
+ self.assertEquals(o.array[0], 1)
+
+ o.array *= 3
+
+ self.assertEquals(len(o.array), 6)
+ self.assertEquals(o.array[0], 1)
+ self.assertEquals(o.array[1], 2)
+ self.assertEquals(o.array[3], 1)
+ self.assertEquals(o.array[4], 2)
+ self.assertEquals(o.array[5], 1)
+ self.assertEquals(o.array[6], 2)
+
+ self.assertEquals(len(observer.values), 3)
+ self.assertEquals(observer.values[-2][-1]['indexes'], NSIndexSet.alloc().initWithIndexesInRange_((2, 4)))
+ self.assertNotIn('old', observer.values[-2][-1])
+ self.assertEquals(observer.values[-2][-1]['new'], [1, 2, 1, 2])
+
+ self.assertNotIn('indexes', observer.values[-1][-1])
+
+ finally:
+ observer.unregister(o, 'array')
+
def testSort(self):
# Use sort method and check that the correct
# KVO events get emitted
- self.fail("todo")
+ observer = OCObserve.alloc().init()
+ l = [2, 4, 1, 3]
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+
+ try:
+ IS = NSIndexSet.alloc().initWithIndexesInRange_((0, 4))
+ self.assertEquals(len(observer.values), 0)
+
+ orig_l = l[:]
+ o.array = l
+
+
+ self.assertEquals(len(observer.values), 1)
+ self.assertNotIn('indexes', observer.values[-1][-1])
+
+ self.assertEquals(o.array[0], 2)
+
+ o.array.sort()
+
+ self.assertEquals(o.array[0], 1)
+ self.assertEquals(o.array[1], 2)
+ self.assertEquals(o.array[2], 3)
+ self.assertEquals(o.array[3], 4)
+ self.assertEquals(len(o.array), 4)
+
+ self.assertEquals(len(observer.values), 2)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS)
+ self.assertEquals(observer.values[-1][-1]['old'], l)
+ self.assertEquals(observer.values[-1][-1]['new'], [1,2,3,4])
+ self.assertEquals(orig_l, l)
+
+ finally:
+ observer.unregister(o, 'array')
def testReverse(self):
# Use reverse method and check that the correct
# KVO events get emitted
- self.fail("todo")
+ observer = OCObserve.alloc().init()
+ l = [2, 4, 1, 3]
+ o = TestArrayPropertyHelper.alloc().init()
+ observer.register(o, 'array')
+
+ try:
+ IS = NSIndexSet.alloc().initWithIndexesInRange_((0, 4))
+ self.assertEquals(len(observer.values), 0)
+
+ orig_l = l[:]
+ o.array = l
+
+
+ self.assertEquals(len(observer.values), 1)
+ self.assertNotIn('indexes', observer.values[-1][-1])
+
+ self.assertEquals(o.array[0], 2)
+
+ o.array.reverse()
+
+ self.assertEquals(o.array[0], 3)
+ self.assertEquals(o.array[1], 1)
+ self.assertEquals(o.array[2], 4)
+ self.assertEquals(o.array[3], 2)
+ self.assertEquals(len(o.array), 4)
+
+ self.assertEquals(len(observer.values), 2)
+ self.assertEquals(observer.values[-1][-1]['indexes'], IS)
+ self.assertEquals(observer.values[-1][-1]['old'], l)
+ self.assertEquals(observer.values[-1][-1]['new'], [3, 1, 4, 2])
+ self.assertEquals(orig_l, l)
+
+ finally:
+ observer.unregister(o, 'array')
+
+ def testObjCAccessors(self):
+ # Check that the right ObjC array accessors are defined and work properly
+ self.assertTrue(TestArrayPropertyHelper.instancesRespondToSelector_(b"setArray:"))
+ self.assertTrue(TestArrayPropertyHelper.instancesRespondToSelector_(b"array"))
+ self.assertTrue(TestArrayPropertyHelper.instancesRespondToSelector_(b"countOfArray"))
+ self.assertTrue(TestArrayPropertyHelper.instancesRespondToSelector_(b"objectInArrayAtIndex:"))
+ self.assertTrue(TestArrayPropertyHelper.instancesRespondToSelector_(b"insertObject:inArrayAtIndex:"))
+ self.assertTrue(TestArrayPropertyHelper.instancesRespondToSelector_(b"removeObjectFromArrayAtIndex:"))
+ self.assertTrue(TestArrayPropertyHelper.instancesRespondToSelector_(b"replaceObjectInArrayAtIndex:withObject:"))
+
+ o = TestArrayPropertyHelper.alloc().init()
+ self.assertEquals(0, o.pyobjc_instanceMethods.countOfArray())
+ self.assertRaises(AttributeError, getattr, o, 'countOfArray')
+
+ o.pyobjc_instanceMethods.insertObject_inArrayAtIndex_('a', 0)
+ self.assertEquals(1, o.pyobjc_instanceMethods.countOfArray())
+ self.assertEquals('a', o.array[0])
+ self.assertEquals('a', o.pyobjc_instanceMethods.objectInArrayAtIndex_(0))
+ o.pyobjc_instanceMethods.replaceObjectInArrayAtIndex_withObject_(0, 'b')
+ self.assertEquals('b', o.array[0])
+ o.pyobjc_instanceMethods.removeObjectFromArrayAtIndex_(0)
+ self.assertEquals(0, o.pyobjc_instanceMethods.countOfArray())
- def testKVOFromObjC(self):
- # Check that the right interfaces are implemented
- # to enable accessing and changing the property
- # from ObjC, using an NSArrayController
- # (Which probably means that a number of KVC methods
- # need to be implemented)
- self.fail("todo")
# Verify docs and/or implementation to check for other
# mutating methods
def testReadingMethods(self):
# Check that all read-only methods work as well
- self.fail("todo")
+
+ o = TestArrayPropertyHelper.alloc().init()
+ o.array = [1, 2, 3, 4]
+
+ self.assertNotIsInstance(o.array, list)
+
+ self.assertEquals(o.array, [1,2,3,4])
+ self.assertNotEquals(o.array, [1,2,3,4, 5])
+
+
+ self.assertTrue(o.array < [1,2,3,4,5])
+ self.assertTrue(o.array <= [1,2,3,4,5])
+ self.assertTrue(o.array <= [1,2,3,4])
+ self.assertTrue(o.array >= [1,2,3,4])
+ self.assertTrue(o.array > [1,2,3])
+
+ self.assertEquals(o.array.count(1), 1)
+ self.assertEquals(o.array.index(4), 3)
def testMutatingReadonlyProperty(self):
# Check that trying to mutate a read-only property
# will raise an exception
- self.fail("todo")
+ o = TestArrayPropertyHelper.alloc().init()
+
+ o._roArray = [1, 2, 3]
+
+ self.assertEquals(list(o.roArray), [1,2,3])
+
+ self.assertRaises(ValueError, o.roArray.append,1)
+ self.assertRaises(ValueError, o.roArray.extend, [1,2])
+ self.assertRaises(ValueError, o.roArray.sort)
+ self.assertRaises(ValueError, o.roArray.reverse)
+ try:
+ o.roArray[0] = 2
+ except ValueError:
+ pass
+ else:
+ self.fail("ValueError not raised")
+
+ try:
+ del o.roArray[0]
+ except ValueError:
+ pass
+ else:
+ self.fail("ValueError not raised")
+
+ try:
+ o.roArray += [4]
+ except ValueError:
+ pass
+ else:
+ self.fail("ValueError not raised")
+
+ try:
+ o.roArray *= 4
+ except ValueError:
+ pass
+ else:
+ self.fail("TypeError not raised")
+
def testMutatingReadonlyPropertyObjC(self):
# Check that trying to mutate a read-only property
# from ObjC will raise an exception
- self.fail("todo")
+ o = TestArrayPropertyHelper.alloc().init()
+ o._roArray = [1,2,3]
+ self.assertEquals(3, o.pyobjc_instanceMethods.countOfRoArray())
+ self.assertRaises(AttributeError, getattr, o, 'countOfRoArray')
+
+ try:
+ o.pyobjc_instanceMethods.insertObject_inRoArrayAtIndex_('a', 0)
+ except ValueError:
+ pass
+ else:
+ self.fail("ValueError not raised")
+
+ self.assertEquals(3, o.pyobjc_instanceMethods.countOfRoArray())
+ self.assertEquals(1, o.pyobjc_instanceMethods.objectInRoArrayAtIndex_(0))
+ try:
+ o.pyobjc_instanceMethods.replaceObjectInRoArrayAtIndex_withObject_(0, 'b')
+ except ValueError:
+ pass
+ else:
+ self.fail("ValueError not raised")
+
+ try:
+ o.pyobjc_instanceMethods.removeObjectFromRoArrayAtIndex_(0)
+ except ValueError:
+ pass
+ else:
+ self.fail("ValueError not raised")
+
if __name__ == "__main__":
------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first