Commits

Ronald Oussoren committed b272a4a

More test improvements

Comments (0)

Files changed (16)

pyobjc-core/.coveragerc

 [report]
 exclude_lines =
     pragma: no 3.x cover
+    pragma: no cover
     def __repr__
     if 0:
     if __name__ == .__main__.:

pyobjc-core/Lib/objc/_convenience_nsarray.py

 
     elif idx < 0:
         idx += len(self)
-        if idx < 0:
-            raise IndexError("list index out of range")
 
     rval = self.objectAtIndex_(idx)
     self.removeObjectAtIndex_(idx)
                 # Empty slice: insert values
                 stop = start
 
-        elif start <= stop:
-            start = stop
-
         anObject = _ensure_array(anObject)
 
         if step == 1:
                 slice_len, len(anObject)))
 
         if step > 0:
-            if anObject is self:
-                toAssign = list(anObject)
-
-            else:
-                toAssign = anObject
+            # NOTE: 'anObject' cannot be 'self' because assigning to an extended
+            # slice cannot change the size of 'self' and slep 1 is handled earlier.
+            toAssign = anObject
 
             for inIdx, outIdx in enumerate(range(start, stop, step)):
                 self.replaceObjectAtIndex_withObject_(outIdx, toAssign[inIdx])
 
-        elif step == 0:
-            raise ValueError("Step 0")
+        # slice.indexes already catches this:
+        #elif step == 0:
+        #    raise ValueError("Step 0")
 
         else:
             if anObject is self:
 
 
 def nsarray_add(self, other):
-    result = NSMutableArray.arrayWithArray_(self)
+    result = NSMutableArray(self)
     result.addObjectsFromArray_(_ensure_array(other))
     return result
 
 
 def nsarray_radd(self, other):
-    result = NSMutableArray.arrayWithArray_(other)
+    result = NSMutableArray(other)
     result.addObjectsFromArray_(self)
     return result
 
 def nsarray__len__(self):
     return self.count()
 
-def nsarray__copy__(self):
+# NOTE: 'no cover' because call of the system array
+# classes are subclasses of NSMutableArray.
+def nsarray__copy__(self):  # pragma: no cover
     return self.copy()
 
 addConvenienceForClass('NSArray', (

pyobjc-core/Lib/objc/_convenience_nsset.py

     return self.containsObject_(value)
 
 def nsset__or__(self, other):
-    if not isinstance(self, collections.Set):
-        raise TypeError("NSSet|value where value is not a set")
     if not isinstance(other, collections.Set):
         raise TypeError("NSSet|value where value is not a set")
     return nsset_union(self, other)
 
 def nsset__ror__(self, other):
-    if not isinstance(self, collections.Set):
-        raise TypeError("value|NSSet where value is not a set")
     if not isinstance(other, collections.Set):
         raise TypeError("value|NSSet where value is not a set")
     return nsset_union(other, self)
 
 def nsset__and__(self, other):
-    if not isinstance(self, collections.Set):
-        raise TypeError("NSSet&value where value is not a set")
     if not isinstance(other, collections.Set):
         raise TypeError("NSSet&value where value is not a set")
     return nsset_intersection(self, other)
 
 def nsset__rand__(self, other):
-    if not isinstance(self, collections.Set):
-        raise TypeError("value&NSSet where value is not a set")
     if not isinstance(other, collections.Set):
         raise TypeError("value&NSSet where value is not a set")
     return nsset_intersection(other, self)
 
 def nsset__sub__(self, other):
-    if not isinstance(self, collections.Set):
-        raise TypeError("NSSet-value where value is not a set")
     if not isinstance(other, collections.Set):
         raise TypeError("NSSet-value where value is not a set")
     return nsset_difference(self, other)
 
-def nsset_rsub__(self, other):
-    if not isinstance(self, collections.Set):
-        raise TypeError("NSSet-value where value is not a set")
+def nsset__rsub__(self, other):
     if not isinstance(other, collections.Set):
         raise TypeError("NSSet-value where value is not a set")
-    return nsset_difference(other, self)
+    return nsset_difference(NSMutableSet(other), self)
 
 def nsset__xor__(self, other):
-    if not isinstance(self, collections.Set):
-        raise TypeError("NSSet-value where value is not a set")
     if not isinstance(other, collections.Set):
         raise TypeError("NSSet-value where value is not a set")
     return nsset_symmetric_difference(other, self)
     def nsset__cmp__(self, other):
         raise TypeError("Cannot compare sets using cmp")
 
-def nsset__length_hint__(self):
-    return len(self)
-
 def nsset_update(self, *others):
     for other in others:
         if isinstance(other, collections.Set):
 addConvenienceForClass('NSSet', (
     ('__len__', lambda self: self.count()),
     ('__iter__', lambda self: nsset__iter__(self)),
-    ('__length_hint__', nsset__length_hint__),
     ('__contains__',  nsset__contains__),
     ('isdisjoint',  nsset_isdisjoint),
     ('union',  nsset_union),
     ('__xor__', nsset__xor__),
     ('__rxor__', nsset__xor__),
     ('__sub__', nsset__sub__),
+    ('__rsub__', nsset__rsub__),
 ))
 
 if sys.version_info[0] == 2:  # pragma: no 3.x cover

pyobjc-core/Lib/objc/_convenience_sequence.py

 
 __all__ = ('addConvenienceForBasicSequence',)
 
-def collection_iter(self):
+def seq_iter(self):
     for idx in range(len(self)):
         yield self[idx]
 
+def seq_len(self):
+    return self.count()
+
+def seq_getitem(self, idx):
+    if isinstance(idx, slice):
+        raise ValueError("Slices not supported")
+
+    if idx < 0:
+        orig_idx = idx
+        idx += seq_len(self)
+
+        if idx < 0:
+            raise IndexError(orig_idx)
+
+    return self.objectAtIndex_(idx)
+
+def seq_setitem(self, idx, value):
+    if isinstance(idx, slice):
+        raise ValueError("Slices not supported")
+
+    if idx < 0:
+        orig_idx = idx
+        idx += seq_len(self)
+
+        if idx < 0:
+            raise IndexError(orig_idx)
+
+    return self.setObject_atIndex_(value, idx)
+
 def addConvenienceForBasicSequence(classname, readonly=True):
     addConvenienceForClass(classname, (
-        ('__len__',  lambda self: self.count()),
-        ('__getitem__', lambda self, idx: self.objectAtIndex_(idx)),
-        ('__iter__', collection_iter),
+        ('__len__',  seq_len),
+        ('__getitem__', seq_getitem),
+        ('__iter__', seq_iter),
     ))
 
     if not readonly:
         addConvenienceForClass(classname, (
-            ('__setitem__', lambda self, idx, value: self.setObject_atIndex_(value, idx)),
+            ('__setitem__', seq_setitem),
         ))
-
-
-# XXX: Move these to another file
-addConvenienceForBasicSequence('WebScriptObject', True)
-addConvenienceForClass('WebScriptObject', (
-    ('count',    lambda self: self.lenght()),
-))
-addConvenienceForBasicSequence('QCStructure', True)

pyobjc-core/Lib/objc/_lazyimport.py

     __slots__ = (
                 '_ObjCLazyModule__bundle', '_ObjCLazyModule__enummap', '_ObjCLazyModule__funcmap',
                 '_ObjCLazyModule__parents', '_ObjCLazyModule__varmap', '_ObjCLazyModule__inlinelist',
-                '_ObjCLazyModule__aliases',
+                '_ObjCLazyModule__aliases', '_ObjCLazyModule__informal_protocols',
             )
 
     def __init__(self, name, frameworkIdentifier, frameworkPath, metadict=None, inline_list=None, initialdict=None, parents=()):
 
         if frameworkIdentifier is not None or frameworkPath is not None:
             self.__bundle = self.__dict__['__bundle__'] = _loadBundle(name, frameworkIdentifier, frameworkPath)
+        else:
+            self.__bundle = None
 
         pfx = name + '.'
         for nm in sys.modules:
         if self.__varmap_dct:
             dct = {}
             objc.loadBundleVariables(self.__bundle, dct,
-                    [ (nm, self.__varmap_dct[nm].encode('ascii')) for nm in self.__varmap_dct ])
+                    [ (nm, self.__varmap_dct[nm].encode('ascii'))
+                        for nm in self.__varmap_dct if not self.__varmap_dct[nm].startswith('=')])
             for nm in dct:
                 if nm not in self.__dict__:
                     self.__dict__[nm] = dct[nm]
 
+            for nm, tp in self.__varmap_dct.items():
+                if tp.startswith('='):
+                    try:
+                        self.__dict__[nm] = objc._loadConstant(nm, tp[1:], True)
+                    except AttributeError:
+                        pass
+
+
             self.__varmap_dct = {}
 
         if self.__varmap:
             varmap = []
+            specials = []
             for nm, tp in re.findall(r"\$([A-Z0-9a-z_]*)(@[^$]*)?(?=\$)", self.__varmap):
-                varmap.append((nm, b'@' if not tp else tp.encode('ascii')))
+                if tp and tp.startswith('@='):
+                    specials.append((nm, tp[2:]))
+                else:
+                    varmap.append((nm, b'@' if not tp else tp[1:].encode('ascii')))
 
             dct = {}
             objc.loadBundleVariables(self.__bundle, dct, varmap)
                 if nm not in self.__dict__:
                     self.__dict__[nm] = dct[nm]
 
+            for nm, tp in specials:
+                try:
+                    self.__dict__[nm] = objc._loadConstant(nm, tp, True)
+                except AttributeError:
+                    pass
+
             self.__varmap = ""
 
         if self.__enummap:
                 if nm not in self.__dict__:
                     self.__dict__[nm] = dct[nm]
 
+            if self.__inlinelist is not None:
+                dct = {}
+                objc.loadFunctionList(
+                    self.__inlinelist, dct, func_list, skip_undefined=True)
+                for nm in dct:
+                    if nm not in self.__dict__:
+                        self.__dict__[nm] = dct[nm]
+
             self.__funcmap = {}
 
         if self.__expressions:
         if self.__varmap_dct:
             if name in self.__varmap_dct:
                 tp = self.__varmap_dct.pop(name)
-                result = objc._loadConstant(name, tp, False)
+                if tp.startswith('='):
+                    tp = tp[1:]
+                    magic = True
+                else:
+                    magic = False
+                result = objc._loadConstant(name, tp, magic)
                 return result
 
         if self.__varmap:
                     return d[name]
 
                 if self.__inlinelist is not None:
-                    try:
-                        objc.loadFunctionList(
-                            self.__inlinelist, d, func_list, skip_undefined=False)
-                    except objc.error:
-                        pass
-
-                    else:
-                        if name in d:
-                            return d[name]
+                    objc.loadFunctionList(
+                        self.__inlinelist, d, func_list, skip_undefined=True)
+                    if name in d:
+                        return d[name]
 
         if self.__expressions:
             if name in self.__expressions:
 
         for name, type, gettypeid_func, tollfree in cftypes:
             if tollfree:
-                for nm in tollfree.split(','):
+                for nm in tollfree.split(','):  # pragma: no branch
                     try:
                         objc.lookUpClass(nm)
                     except objc.error:
                         break
                 try:
                     v = objc.registerCFSignature(name, type, None, tollfree)
-                    if v is not None:
-                        self.__dict__[name] = v
-                        continue
+                    self.__dict__[name] = v
+                    continue
                 except objc.nosuchclass_error:
                     pass
 
                 # function. Proxy using the generic CFType
                 if tollfree is None:
                     v = objc.registerCFSignature(name, type, None, 'NSCFType')
-                    if v is not None:
-                        self.__dict__[name] = v
+                    self.__dict__[name] = v
                 continue
 
             v = objc.registerCFSignature(name, type, func())

pyobjc-core/Lib/objc/_pycoder.py

 
     encode_dispatch[long] = save_long
 
-else: # pragma: no cover (py3k)
+else: # pragma: no 2.x cover
     def save_int(coder, obj):
         if coder.allowsKeyedCoding():
             coder.encodeInt_forKey_(kOP_LONG, kKIND)

pyobjc-core/Modules/objc/informal-protocol.m

 
     if (selToProtocolMapping) {
         for (i = 0; i < len; i++) {
+            PyObject* cur;
+            int r;
             PyObjCSelector* tmp =
                 (PyObjCSelector*)PyTuple_GET_ITEM(
                     self->selectors, i);
 
-            PyDict_DelItemString(selToProtocolMapping,
-                sel_getName(tmp->sel_selector));
+            /* Remove method from the selector to protocol mappping,
+             * but only if this protocol is registered for the selector.
+             */
+            cur = PyDict_GetItemString(selToProtocolMapping, sel_getName(tmp->sel_selector));
+            if (cur == (PyObject*)self) {
+                r = PyDict_DelItemString(selToProtocolMapping,
+                    sel_getName(tmp->sel_selector));
+                if (r == -1) {
+                    /* Shouldn't happen */
+                    PyErr_Clear();
+                }
+            }
         }
     }
 

pyobjc-core/Modules/objc/objc-object.h

     PyObject_HEAD
 
     __strong id objc_object;
-    int         flags;
+    unsigned int flags;
 } PyObjCObject;
 
 typedef struct {
-    PyObject_HEAD
-    __strong id objc_object;
-
-    int         flags;
+    PyObjCObject base;
     PyObjCMethodSignature* signature;
 } PyObjCBlockObject;
 

pyobjc-core/Modules/objc/objc-object.m

 }
 
 static PyObject*
+obj_get_flags(PyObject* self, void* closure __attribute__((__unused__)))
+{
+    return Py_BuildValue("I", PyObjCObject_GetFlags(self));
+}
+
+static PyObject*
 obj_get_blocksignature(PyObject* self, void* closure __attribute__((__unused__)))
 {
     if (PyObjCObject_IsBlock(self)) {
         .doc    = "Call signature for a block, or None",
     },
     {
+        .name   = "__flags__",
+        .get    = obj_get_flags,
+    },
+    {
         .name   = NULL  /* SENTINEL */
     }
 };

pyobjc-core/Modules/objc/test/sequence.m

+/*
+ * This module is used in the unittests for the sequence API
+ */
+#include "Python.h"
+#include "pyobjc-api.h"
+
+#import <Foundation/Foundation.h>
+
+@interface OC_TestSequence : NSObject
+{
+    NSObject* objects[128];
+    NSUInteger len;
+}
+-(id)initWithArray:(NSArray*)array;
+-(NSUInteger)count;
+-(id)objectAtIndex:(NSUInteger)idx;
+
+@end
+
+@implementation OC_TestSequence
+
+-(id)initWithArray:(NSArray*)array
+{
+    NSUInteger i;
+
+    self = [super init];
+    if (!self) return nil;
+
+    len = MIN([array count], (NSUInteger)128);
+    for (i = 0; i < len; i++) {
+        objects[i] = [[array objectAtIndex:i] retain];
+    }
+    return self;
+}
+
+-(void)dealloc
+{
+    NSUInteger i;
+    for (i = 0; i < len; i++) {
+        [objects[i] release];
+    }
+    [super dealloc];
+}
+
+-(NSUInteger)count
+{
+    return len;
+}
+
+-(id)objectAtIndex:(NSUInteger)idx
+{
+    if (idx >= len) {
+        [NSException raise:NSRangeException format:@"Index %ld is out of range", (long)idx];
+    }
+    return [[objects[idx] retain] autorelease];
+}
+
+@end
+
+
+@interface OC_TestMutableSequence : OC_TestSequence
+{
+}
+-(void)setObject:(id)value atIndex:(NSUInteger)idx;
+@end
+
+@implementation OC_TestMutableSequence
+-(void)setObject:(id)value atIndex:(NSUInteger)idx
+{
+    if (idx >= len) {
+        [NSException raise:NSRangeException format:@"Index %ld is out of range", (long)idx];
+    }
+    [value retain];
+    [objects[idx] release];
+    objects[idx] = value;
+}
+@end
+
+
+static PyMethodDef mod_methods[] = {
+    { 0, 0, 0, 0 }
+};
+
+#if PY_VERSION_HEX >= 0x03000000
+
+static struct PyModuleDef mod_module = {
+    PyModuleDef_HEAD_INIT,
+    "sequence",
+    NULL,
+    0,
+    mod_methods,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+#define INITERROR() return NULL
+#define INITDONE() return m
+
+PyObject* PyInit_sequence(void);
+
+PyObject* __attribute__((__visibility__("default")))
+PyInit_sequence(void)
+
+#else
+
+#define INITERROR() return
+#define INITDONE() return
+
+void initsequence(void);
+
+void __attribute__((__visibility__("default")))
+initsequence(void)
+#endif
+{
+    PyObject* m;
+
+#if PY_VERSION_HEX >= 0x03000000
+    m = PyModule_Create(&mod_module);
+#else
+    m = Py_InitModule4("sequence", mod_methods,
+        NULL, NULL, PYTHON_API_VERSION);
+#endif
+    if (!m) {
+        INITERROR();
+    }
+
+    if (PyObjC_ImportAPI(m) < 0) {
+        INITERROR();
+    }
+    if (PyModule_AddObject(m, "OC_TestSequence",
+        PyObjC_IdToPython([OC_TestSequence class])) < 0) {
+        INITERROR();
+    }
+    if (PyModule_AddObject(m, "OC_TestMutableSequence",
+        PyObjC_IdToPython([OC_TestMutableSequence class])) < 0) {
+        INITERROR();
+    }
+
+    INITDONE();
+}

pyobjc-core/PyObjCTest/test3_dict_interface.py

 - Do the same for sets (NSSet) and lists (NSArray)
 """
 from PyObjCTools.TestSupport import *
+import operator
 import objc
 
 # Import some of the stdlib tests
         self.assertTrue({1} == self.dictClass().dictionaryWithDictionary_({1:1}).keys())
         self.assertEqual(self.dictClass().dictionaryWithDictionary_({1:1}).keys() | {2}, {1, 2})
         self.assertEqual({2} | self.dictClass().dictionaryWithDictionary_({1:1}).keys(), {1, 2})
+        self.assertFalse(self.dictClass().dictionaryWithDictionary_({1:1}).keys() == [1])
+
         # And a few for .items()
         self.assertTrue(self.dictClass().dictionaryWithDictionary_({1:1}).items() == {(1,1)})
         self.assertTrue({(1,1)} == self.dictClass().dictionaryWithDictionary_({1:1}).items())
         self.assertEqual(self.dictClass().dictionaryWithDictionary_({1:1}).items() | {2}, {(1,1), 2})
         self.assertEqual({2} | self.dictClass().dictionaryWithDictionary_({1:1}).items(), {(1,1), 2})
+        self.assertFalse(self.dictClass().dictionaryWithDictionary_({1:1}).items() == [(1,1)])
 
 
 class TestNSMutableDictionaryInterface (TestNSDictionaryInterface):
         self.assertTrue(isinstance(d.values(), collections.ValuesView))
         self.assertTrue(isinstance(d.items(), collections.ItemsView))
 
+class TestPyObjCDict (TestCase):
+    def test_comparison(self):
+        self.assertRaises(TypeError, operator.lt, {}, {})
+        self.assertRaises(TypeError, operator.le, {}, {})
+        self.assertRaises(TypeError, operator.gt, {}, {})
+        self.assertRaises(TypeError, operator.ge, {}, {})
+
+        self.assertRaises(TypeError, operator.lt, NSDictionary(), {})
+        self.assertRaises(TypeError, operator.le, NSDictionary(), {})
+        self.assertRaises(TypeError, operator.gt, NSDictionary(), {})
+        self.assertRaises(TypeError, operator.lt, {}, NSDictionary())
+        self.assertRaises(TypeError, operator.le, {}, NSDictionary())
+        self.assertRaises(TypeError, operator.gt, {}, NSDictionary())
+
+        self.assertFalse(NSMutableDictionary() == [])
+        self.assertFalse(NSDictionary() == [])
+        self.assertFalse(NSMutableDictionary() == 42)
+        self.assertFalse(NSDictionary() == 42)
+        self.assertFalse(NSMutableDictionary() == object())
+        self.assertFalse(NSDictionary() == object())
+
+    def test_creation(self):
+        for dict_type in (NSDictionary, NSMutableDictionary):
+            v = dict_type()
+            self.assertIsInstance(v, dict_type)
+            self.assertEqual(len(v), 0)
+
+            v = dict_type({1:2, 2:3})
+            self.assertIsInstance(v, dict_type)
+            self.assertEqual(len(v), 2)
+            self.assertEqual(v[1], 2)
+            self.assertEqual(v[2], 3)
+
+            v = dict_type([(1, -1), (2, 9)])
+            self.assertIsInstance(v, dict_type)
+            self.assertEqual(len(v), 2)
+            self.assertEqual(v[1], -1)
+            self.assertEqual(v[2], 9)
+
+            v = dict_type(v for v in [(1, -1), (2, 9)])
+            self.assertIsInstance(v, dict_type)
+            self.assertEqual(len(v), 2)
+            self.assertEqual(v[1], -1)
+            self.assertEqual(v[2], 9)
+
+            self.assertRaises(TypeError, dict_type, (1,2), (3,4))
+
+            v = dict_type(a=3, b=4)
+            self.assertEqual(len(v), 2)
+            self.assertEqual(v['a'], 3)
+            self.assertEqual(v['b'], 4)
+
+            v = dict_type((v for v in [(1, -1), (2, 9)]), a='hello', b='world')
+            self.assertIsInstance(v, dict_type)
+            self.assertEqual(len(v), 4)
+            self.assertEqual(v[1], -1)
+            self.assertEqual(v[2], 9)
+            self.assertEqual(v['a'], 'hello')
+            self.assertEqual(v['b'], 'world')
+
+    def test_values(self):
+        py = dict(a=4, b=3)
+        oc = NSDictionary(a=4, b=3)
+
+        self.assertIn(4, py.values())
+        self.assertIn(4, oc.values())
+        self.assertNotIn(9, py.values())
+        self.assertNotIn(9, oc.values())
+
+    def test_view_set(self):
+        oc = NSDictionary(a=1, b=2, c=3, d=4, e=5)
+
+        v = oc.keys() | {'a', 'f' }
+        self.assertEqual(v, {'a', 'b', 'c', 'd', 'e', 'f' })
+        self.assertIsInstance(v, set)
+        self.assertRaises(TypeError, operator.or_, oc.keys(), ('a', 'f'))
+        self.assertRaises(TypeError, operator.or_, ('a', 'f'), oc.keys())
+
+        v = oc.keys() & {'a', 'f' }
+        self.assertEqual(v, {'a'})
+        self.assertIsInstance(v, set)
+        self.assertRaises(TypeError, operator.and_, oc.keys(), ('a', 'f'))
+        self.assertRaises(TypeError, operator.and_, ('a', 'f'), oc.keys())
+
+        v = oc.keys() ^ {'a', 'f' }
+        self.assertEqual(v, {'b', 'c', 'd', 'e', 'f'})
+        self.assertIsInstance(v, set)
+        self.assertRaises(TypeError, operator.xor, oc.keys(), ('a', 'f'))
+        self.assertRaises(TypeError, operator.xor, ('a', 'f'), oc.keys())
+
+        v = oc.keys() - {'a', 'f' }
+        self.assertEqual(v, {'b', 'c', 'd', 'e'})
+        self.assertIsInstance(v, set)
+        self.assertRaises(TypeError, operator.sub, oc.keys(), ('a', 'f'))
+        self.assertRaises(TypeError, operator.sub, ('a', 'f'), oc.keys())
+
+        self.assertRaises(TypeError, operator.lt, oc.keys(), ('a', 'f'))
+        self.assertRaises(TypeError, operator.le, oc.keys(), ('a', 'f'))
+        self.assertRaises(TypeError, operator.gt, oc.keys(), ('a', 'f'))
+        self.assertRaises(TypeError, operator.ge, oc.keys(), ('a', 'f'))
+
 if __name__ == "__main__":
     main()

pyobjc-core/PyObjCTest/test_array_interface.py

 from test import list_tests, seq_tests
 import objc
 import sys
+import operator
 
 # Import some of the stdlib tests
 from test import mapping_tests
 class ArrayTests (seq_tests.CommonTest):
     type2test = NSArray
 
+    def test_from_iterator(self):
+        a = NSArray(i for i in range(5))
+        self.assertEqual(a, NSArray([0,1,2,3,4]))
+
+    def test_pyobjc_copy(self):
+        a = NSArray()
+        b = a.copy()
+        self.assertEqual(a, b)
+        self.assertIsInstance(b, NSArray)
+
+        a = NSArray([0])
+        b = a.copy()
+        self.assertEqual(a, b)
+        self.assertIsInstance(b, NSArray)
+
+        a = NSArray([0, 2])
+        b = a.copy()
+        self.assertEqual(a, b)
+        self.assertIsInstance(b, NSArray)
+
+
     @onlyIf(0, "Not relevant for NSArray")
     def test_pickle(self):
         pass
     def test_pickle(self):
         pass
 
+    def test_pyobjc_setitem(self):
+        l = [1,2,3,4,5,6,7,8,9]
+        a = NSMutableArray([1,2,3,4,5,6,7,8,9])
+        self.assertRaises(TypeError, operator.setitem, a, 'a', 'b')
+        self.assertRaises(ValueError, operator.setitem, a, slice(1,4,0), ('c', 'd'))
+        a[1:4] = a
+        l[1:4] = l
+        self.assertEqual(a, NSMutableArray(l))
+
+        l = [1,2,3,4]
+        a = NSMutableArray([1,2,3,4])
+        l[-2:2] = 'a'
+        a[-2:2] = 'a'
+        self.assertEqual(a, NSMutableArray(l))
+
+        l = [1,2,3,4]
+        a = NSMutableArray([1,2,3,4])
+        self.assertRaises(ValueError, operator.setitem, a, slice(None, None,2), a)
+        self.assertRaises(ValueError, operator.setitem, a, slice(None, None,2), l)
+
+    def test_pyobjc_radd(self):
+        a = NSArray([1,2])
+
+        res = a + [3,4]
+        self.assertEqual(res, NSArray([1,2,3,4]))
+        self.assertIsInstance(res, NSArray)
+
+        res = a + (3,4)
+        self.assertEqual(res, NSArray([1,2,3,4]))
+        self.assertIsInstance(res, NSArray)
+
+        res = a + (x for x in (3,4))
+        self.assertEqual(res, NSArray([1,2,3,4]))
+        self.assertIsInstance(res, NSArray)
+
+        res = [3,4] + a
+        self.assertEqual(res, NSArray([3,4, 1, 2]))
+        self.assertIsInstance(res, NSArray)
+
+        res = (3,4) + a
+        self.assertEqual(res, NSArray([3,4, 1, 2]))
+        self.assertIsInstance(res, NSArray)
+
+        res = (x for x in (3,4)) + a
+        self.assertEqual(res, NSArray([3,4, 1, 2]))
+        self.assertIsInstance(res, NSArray)
+
+
     def test_pyobjc_insert(self):
         u = self.type2test([1,2,3,4,])
         u.insert(-8, 0)
         u = self.type2test([1,2,3,4,])
         self.assertEqual(u.pop(-2), 3)
 
-        v = self.type2test([1,2,4,])
 
     def test_pyobjc_delitem(self):
         u = self.type2test([1,2,3,4,])
         self.assertNotEqual(id(a), id(b))
         self.assertEqual(a, b)
 
-
-
-
-
-
     def test_index(self):
         # As superclass, but without calls to u.count
         u = self.type2test([0, 1])
 
 
     def test_sort(self):
-        base = [2,1,5,4,3]
+        base = [2,1,5,4,1,3]
 
         l = self.type2test(base)
         l.sort()
-        self.assertEqual(l, self.type2test([1,2,3,4,5]))
+        self.assertEqual(l, self.type2test([1,1,2,3,4,5]))
 
         l = self.type2test(base)
         l.sort(reverse=True)
-        self.assertEqual(l, self.type2test([5,4,3,2,1]))
+        self.assertEqual(l, self.type2test([5,4,3,2,1,1]))
 
         base = [-2,1,-5,4,3]
         l = self.type2test(base)

pyobjc-core/PyObjCTest/test_convenience.py

 import operator
 import sys
 
+from PyObjCTest.sequence import *
+objc.addConvenienceForBasicSequence('OC_TestSequence', False)
+objc.addConvenienceForBasicSequence('OC_TestMutableSequence', True)
+
 class OC_WithHash (objc.lookUpClass('NSObject')):
     def initWithHash_(self, value):
         self = objc.super(OC_WithHash, self).init()
     def hash(self):
         return self._hash
 
+    def someKey(self):
+        objc.lookUpClass('NSException').alloc().initWithName_reason_userInfo_(
+            'NSRangeException', 'Test exception', {}).raise__()
+        return 1
+
+    def someOtherKey(self):
+        raise KeyError()
+
+class OC_Compared (objc.lookUpClass('NSObject')):
+    def initWithValue_(self, value):
+        self = super(OC_Compared, self).init()
+        if self is None:
+            return None
+
+        self._value = value
+        return self
+
+    @objc.typedSelector(objc._C_NSBOOL + b"@:@")
+    def isEqualTo_(self, other):
+        return self.compare_(other) == 0
+
+    @objc.typedSelector(objc._C_NSBOOL + b"@:@")
+    def isNotEqualTo_(self, other):
+        return self.compare_(other) != 0
+
+    @objc.typedSelector(objc._C_NSInteger + b"@:@")
+    def compare_(self, other):
+        if isinstance(other, OC_Compared):
+            other = other._value
+
+        if self._value < other:
+            return -1
+
+        elif self._value > other:
+            return 1
+
+        else:
+            return 0
 
 
 class TestBasicConvenience (TestCase):
         self.assertEqual(v.hash(), 2**64-1)
         self.assertTrue(-sys.maxsize-1 <= hash(v) <= sys.maxsize )
 
+    def test_comparisons(self):
+        o1 = objc.lookUpClass('NSObject').alloc().init()
+        o2 = objc.lookUpClass('NSObject').alloc().init()
+
+        self.assertTrue(o1 == o1)
+        self.assertFalse(o1 == o2)
+        self.assertTrue(o1 != o2)
+        self.assertFalse(o1 != o1)
+
+        o1 = OC_Compared.alloc().initWithValue_(21)
+        o2 = OC_Compared.alloc().initWithValue_(42)
+        o3 = OC_Compared.alloc().initWithValue_(42)
+
+        self.assertTrue(o1 < o2)
+        self.assertTrue(o1 <= o2)
+        self.assertTrue(o2 == o3)
+        self.assertTrue(o1 != o2)
+        self.assertTrue(o2 <= o3)
+        self.assertTrue(o2 >= o3)
+        self.assertTrue(o2 > o1)
+
+        self.assertFalse(o2 < o1)
+        self.assertFalse(o2 <= o1)
+        self.assertFalse(o1 == o3)
+        self.assertFalse(o2 != o3)
+        self.assertFalse(o2 <= o1)
+        self.assertFalse(o1 >= o3)
+        self.assertFalse(o1 > o2)
+
 class TestNSDecimalNumber (TestCase):
     def setUp(self):
         self.NSDecimalNumber = objc.lookUpClass('NSDecimalNumber')
         self.assertRaises(TypeError, lambda: o._[42])
         self.assertEqual(repr(o._), '<KVC accessor for %r>'%(o,))
         self.assertRaises(AttributeError, getattr, o._, 'nosuchattr')
-        self.assertRaises(TypeError, o._.__setitem__, 42)
+        self.assertRaises(AttributeError, getattr, o._, '')
+        self.assertRaises(TypeError, o._.__getitem__, 42)
 
         o = objc.lookUpClass('NSMutableDictionary').dictionary()
         o._.key1 = 1
 
         self.assertEqual(o, {'key1': 1, 'key2': 2 })
         self.assertRaises(AttributeError, o._.nosuchattr)
-        self.assertRaises(TypeError, o._.__setitem__, 42)
+        self.assertRaises(TypeError, o._.__setitem__, 42, 1)
 
+        o = OC_WithHash.alloc().initWithHash_(1)
+        self.assertRaises(IndexError, getattr, o._, 'someKey')
+        self.assertRaises(KeyError, getattr, o._, 'someOtherKey')
+
+
+class TestSequences (TestCase):
+    def test_reading(self):
+        o = OC_TestSequence.alloc().initWithArray_(['a', 'b', 'c', 'd'])
+
+        self.assertEqual(len(o), 4)
+        self.assertEqual(o[0], 'a')
+        self.assertEqual(o[3], 'd')
+        self.assertEqual(o[-1], 'd')
+        self.assertEqual(o[-3], 'b')
+
+        self.assertRaises(IndexError, operator.getitem, o, 6)
+        self.assertRaises(IndexError, operator.getitem, o, -6)
+        self.assertRaises(ValueError, operator.getitem, o, slice(1, 3))
+
+        self.assertEqual(list(iter(o)), ['a', 'b', 'c', 'd'])
+        self.assertRaises(AttributeError, operator.setitem, o, 1, 'A')
+
+        o = OC_TestSequence.alloc().initWithArray_([])
+        self.assertEqual(list(iter(o)), [])
+
+    def test_writing(self):
+        o = OC_TestMutableSequence.alloc().initWithArray_(['a', 'b', 'c', 'd'])
+
+        o[0] = 'A'
+        self.assertEqual(o[0], 'A')
+
+        o[2] = 'C'
+        self.assertEqual(o[2], 'C')
+
+        o[-3] = 'X'
+        self.assertEqual(o[1], 'X')
+
+        self.assertEqual(list(o), ['A', 'X', 'C', 'd'])
+
+        self.assertRaises(IndexError, operator.setitem, o, 6, 'x')
+        self.assertRaises(IndexError, operator.setitem, o, -7, 'x')
+        self.assertRaises(ValueError, operator.setitem, o, slice(1, 3), (1,2))
 
 if __name__ == "__main__":
     main()

pyobjc-core/PyObjCTest/test_lazy_import.py

 import struct
 import operator
 
+from PyObjCTest import metadatafunction
+
 if sys.version_info[0] == 3:  # pragma: no 2.x cover; pragma: no branch
     long = int
 
     def do_test_all_types(self, all):
         metadict = {
             'nometadata': 42, # Ignored...
+            'protocols': {'NSMachPortDelegateMethods': objc.informal_protocol('NSMachPortDelegateMethods', [objc.selector(None, b'handleMachMessage:', b'v@:^v', isRequired=False)]) },
             'constants': '$NSWorkspaceMoveOperation$NSWorkspaceCopyOperation@@$',
             'constants_dict': {
                 'NSWorkspaceLinkOperation': '@',
         self.assertEqual(mod.doc_string, initial_dict['__doc__'])
         self.assertRaises(AttributeError, getattr, mod, 'invalid_alias')
         self.assertIsInstance(mod.NSWorkspaceMoveOperation, objc.pyobjc_unicode)
+        self.assertTrue((mod.NSWorkspaceMoveOperation.nsstring().__flags__ & 0x10) == 0x00)
         self.assertIsInstance(mod.NSWorkspaceCopyOperation, objc.pyobjc_unicode)
         self.assertIsInstance(mod.NSWorkspaceLinkOperation, objc.pyobjc_unicode)
+
         self.assertIsInstance(mod.NSUnderlineByWordMask, (int, long))
         self.assertEqual(mod.NSAWTEventType, 16)
         self.assertEqual(mod.NSAboveBottom, 4)
         self.assertEqual(mod.NSWindowWillCloseNotification, 100)
         self.assertNotIn('__doc__', mod.__all__)
 
+        self.assertIn('NSMachPortDelegateMethods', mod._ObjCLazyModule__informal_protocols)
+
     def test_without_framework(self):
         initial_dict = {
                 '__doc__': 'rootless test module',
             'enums': '$NSAWTEventType@16$NSAboveBottom@4$NSAboveTop@1$',
 
             'functions': {
-                'NSRectClipList': (
-                    sel32or64(b'v^{_NSRect={_NSPoint=ff}{_NSSize=ff}}i', b'v^{CGRect={CGPoint=dd}{CGSize=dd}}q'),
-                    '',
-                    {
-                        'arguments': {
-                            0: {
-                                'c_array_length_in_arg': 1,
-                                'type_modifier': b'n'
-                            }
-                        }
-                    }
-                ),
-                'NSAccessibilityActionDescription': (
-                    b'@@', '', {}
-                ),
+                'ABPersonSetImageData': (objc._C_BOOL + objc._C_ID + objc._C_ID, '', {}),
             },
             'aliases': {
                 'doc_string': '__doc__',
         self.assertEqual(mod.__doc__, mod.doc_string)
         self.assertEqual(mod.NSAboveBottom, 4)
         self.assertEqual(mod.mysum, mod.NSAWTEventType + mod.NSAboveBottom + 3)
-        self.assertRaises(AttributeError, getattr, mod, 'NSRectClipList')
+        self.assertRaises(AttributeError, getattr, mod, 'ABPersonSetImageData')
         self.assertRaises(AttributeError, getattr, mod, 'ABAddressBookErrorDomain')
         self.assertRaises(AttributeError, getattr, mod, 'ABMultiValueIdentifiersErrorKey')
 
                 if nm in sys.modules:
                     del sys.modules[nm]
 
-    def test_inlinetab(self):
+    def test_inline_list(self):
         # Use inlinetab from PyObjCTest.metadatafunction extension
         # -> Also check that '__all__' processing loads inline functions!
-        self.fail()
+        metadict = {
+            'functions': {
+                "makeArrayWithFormat_": (b'@@', '',
+                    dict(
+                        variadic=True,
+                        arguments={
+                            0: dict(printf_format=True),
+                        }
+                )),
+                "makeArrayWithCFormat_": (b'@*', '',
+                    dict(
+                        variadic=True,
+                        arguments={
+                            0: dict(printf_format=True),
+                        }
+                )),
+                "make4Tuple_": (b'@^d', '',
+                     dict(
+                     arguments={
+                        0:  dict(type_modifier=objc._C_IN, c_array_of_fixed_length=4, null_accepted=False),
+                     }
+                )),
+                "NoSuchFunction": (b'@d', '', {}),
+            }
+        }
 
-    def test_magic(self):
-        # Create 'magic cookie' variable, and verify that it is one
-        self.fail()
+        inline_list = metadatafunction.function_list
+        mod = objc.ObjCLazyModule ('MyFramework', None, None, metadict, inline_list, {}, ())
+        self.assertIsInstance(mod, objc.ObjCLazyModule)
+
+        self.assertIsInstance(mod.makeArrayWithFormat_, objc.function)
+        v = mod.makeArrayWithFormat_("%3d", 10)
+        self.assertEqual(list(v), [ "%3d", " 10"])
+        self.assertRaises(AttributeError, getattr, mod, 'NoSuchFunction')
+
+        mod.make4Tuple_ = 42
+        self.assertIn('makeArrayWithFormat_', mod.__all__)
+        self.assertIn('makeArrayWithCFormat_', mod.__all__)
+        self.assertEqual(mod.make4Tuple_, 42)
 
     def test_cftype(self):
-        # create some cftypes:
-        # - with and without tollfree bridging
-        # - with and without typeid function
-        self.fail()
+        metadict = {
+            'cftypes': [
+                ('CFAllocatorRef', b'^{__CFAllocator=}', 'CFAllocatorGetTypeID', None),
+                ('CFArrayRef', b'^{__CFArray=}', 'CFArrayGetTypeID', 'DoesNotExist,NSArray'),
+                ('CFAttributedStringRef', b'^{__CFAttributedString=}', 'CFAttributedStringGetTypeID', '__NSCFAttributedString,NSCFAttributedString'),
+                ('CFBagRef', b'^{__CFBag=}', 'CFBagGetTypeID', None),
+                ('CFNoType', b'^{__CFNoType', 'CFNoTypeGetTypeID', 'DoesNotExist'),
+            ],
+            'functions': {
+                'CFAllocatorGetTypeID': (objc._C_NSUInteger, ''),
+                'CFArrayGetTypeID': (objc._C_NSUInteger, ''),
+            },
+            'constants': '$kCFAllocatorDefault@=^{__CFAllocator=}$kCFAllocatorMalloc@=^{__CFAllocator=}$kCFAllocatorMissing@=^{__CFAllocator=}$',
+            'constants_dict': {
+                'kCFAllocatorSystemDefault': '=^{__CFAllocator=}',
+                'kCFAllocatorMallocZone': '=^{__CFAllocator=}',
+                'kCFAllocatorMissingZone': '=^{__CFAllocator=}',
+                'kCFAllocatorMissingOtherZone': '=^{__CFAllocator=}',
+            }
+        }
+        mod = objc.ObjCLazyModule ('AppKit', None, '/System/Library/Frameworks/CoreFoundation.framework', metadict, None, {}, ())
 
-    def test_informal_protocols(self):
-        # Add informal protocols to metadict, ensure
-        # the are stored in a private attribute (to keep
-        # them alive), but aren't exposed as attributes
-        self.fail()
+        # Ensure that all types are loaded:
+        self.assertIn('CFAllocatorRef', mod.__dict__)
+        self.assertIn('CFArrayRef', mod.__dict__)
+        self.assertIn('CFAttributedStringRef', mod.__dict__)
+        self.assertIn('CFBagRef', mod.__dict__)
+        self.assertNotIn('CFNoType', mod.__dict__)
+
+        # Type validation:
+        self.assertIn('NSCFType', mod.CFAllocatorRef.__bases__[0].__name__)
+        self.assertIs(mod.CFArrayRef, objc.lookUpClass('NSArray'))
+        self.assertIn(mod.CFAttributedStringRef, (objc.lookUpClass('NSCFAttributedString'), objc.lookUpClass('__NSCFAttributedString')))
+        self.assertIn('NSCFType', mod.CFBagRef.__name__)
+        self.assertIsNot(mod.CFBagRef, mod.CFAllocatorRef)
+
+
+        # Tests for 'magic cookie' constants:
+        self.assertIsInstance(mod.kCFAllocatorDefault, objc.objc_object)
+        self.assertTrue((mod.kCFAllocatorDefault.__flags__ & 0x10) == 0x10)
+        self.assertIsInstance(mod.kCFAllocatorDefault, mod.CFAllocatorRef)
+
+        self.assertIsInstance(mod.kCFAllocatorSystemDefault, objc.objc_object)
+        self.assertTrue((mod.kCFAllocatorSystemDefault.__flags__ & 0x10) == 0x10)
+        self.assertIsInstance(mod.kCFAllocatorSystemDefault, mod.CFAllocatorRef)
+
+        self.assertRaises(AttributeError, getattr, mod, 'kCFAllocatorMissing')
+        self.assertRaises(AttributeError, getattr, mod, 'kCFAllocatorMissingZone')
+
+        self.assertIn('kCFAllocatorDefault', mod.__all__)
+        self.assertIn('kCFAllocatorSystemDefault', mod.__all__)
+        self.assertIn('kCFAllocatorMallocZone', mod.__all__)
+        self.assertIn('kCFAllocatorMalloc', mod.__all__)
+        self.assertRaises(AttributeError, getattr, mod, 'kCFAllocatorOtherMissingZone')
+
+        self.assertIsInstance(mod.kCFAllocatorMalloc, objc.objc_object)
+        self.assertTrue((mod.kCFAllocatorMalloc.__flags__ & 0x10) == 0x10)
+        self.assertIsInstance(mod.kCFAllocatorMalloc, mod.CFAllocatorRef)
+
+        self.assertIsInstance(mod.kCFAllocatorMallocZone, objc.objc_object)
+        self.assertTrue((mod.kCFAllocatorMallocZone.__flags__ & 0x10) == 0x10)
+        self.assertIsInstance(mod.kCFAllocatorMallocZone, mod.CFAllocatorRef)
 
 if __name__ == "__main__":
     main()

pyobjc-core/PyObjCTest/test_set_interface.py

 
 import objc
 import operator
+import collections
 NSSet = objc.lookUpClass('NSSet')
 NSMutableSet = objc.lookUpClass('NSMutableSet')
 
 import test.test_set
 from test.test_set import PassThru, check_pass_thru
 test.test_set.empty_set = NSMutableSet()
+import operator
 
 
 import sys
         return list(range(*args))
 
 
+class TestPyObjCSet (TestCase):
+    def test_reverse_operator(self):
+
+        class MySet (collections.Set):
+            def __init__(self, init=()):
+                self._value = list(init)
+
+            def __iter__(self):
+                return iter(self._value)
+
+            def __contains__(self, value):
+                return value in self._value
+
+            def __len__(self):
+                return len(self._value)
+
+            def __or__(self, other): return NotImplemented
+            def __and__(self, other): return NotImplemented
+            def __xor__(self, other): return NotImplemented
+            def __sub__(self, other): return NotImplemented
+            def __add__(self, other): return NotImplemented
+
+        s = NSSet([1,2,3])
+
+        res = MySet([3,4]) | s
+        self.assertEqual(res, NSSet([1,2,3,4]))
+        self.assertIsInstance(res, NSSet)
+        self.assertRaises(TypeError, operator.or_,  (3,4), s)
+
+        res = MySet([3,4]) & s
+        self.assertEqual(res, NSSet([3]))
+        self.assertIsInstance(res, NSSet)
+        self.assertRaises(TypeError, operator.and_,  (3,4), s)
+
+        res = MySet([3,4]) - s
+        self.assertEqual(res, NSSet([4]))
+        self.assertIsInstance(res, NSSet)
+
+        res = MySet([3,4]) ^ s
+        self.assertEqual(res, NSSet([1,2,4]))
+        self.assertIsInstance(res, NSSet)
+
+    def test_subset(self):
+        s = set([1,2,3])
+        self.assertTrue(s.issubset([1,2,3,4]))
+        self.assertFalse(s.issubset([1,2,4,5]))
+
+        s = NSSet([1,2,3])
+        self.assertTrue(s.issubset([1,2,3,4]))
+        self.assertFalse(s.issubset([1,2,4,5]))
+
+    def test_superset(self):
+        s = set([1,2,3])
+        self.assertTrue(s.issuperset([1,2]))
+        self.assertFalse(s.issuperset([1,5]))
+
+        s = NSSet([1,2,3])
+        self.assertTrue(s.issuperset([1,2]))
+        self.assertFalse(s.issuperset([1,5]))
+
+    def test_conversion(self):
+        s = NSSet([1,2,3])
+        self.assertItemsEqual(list(s), [1,2,3])
+
+        it = iter(s)
+        self.assertItemsEqual(list(it), [1,2,3])
+
+        it = iter(s)
+        it.next()
+        v = list(it)
+        self.assertEqual(len(v), 2)
+        seen = set()
+        for x in v:
+            self.assertIn(x, s)
+            self.assertNotIn(x, seen)
+            seen.add(x)
 
 
 class TestSet (test.test_set.TestJointOps, TestCase):
         n  = self.thetype(s)
         self.assertIsInstance(n, self.thetype)
         self.assertEqual(n, s)
-        
+
     def test_copy(self):
         dup = self.s.copy()
         self.assertEqual(id(self.s), id(dup))
                 self.assertRaises(ZeroDivisionError, getattr(set('january'), methname), test.test_set.E(data))
 
 
-
-
-
-
 class TestGraphs (test.test_set.TestGraphs):
     def setUp(self):
         test.test_set.set = NSMutableSet
 
 
 
-
-
-
-
-
 if __name__ == "__main__":
     main()
 Short term
 ----------
 
+* Exception translation to ObjC: KeyError to NSRangeException etc.
+
 * AppHelper doesn't work? I got an objc stacktrace with an exception in one of the webkit examples
 
 * All examples should work cleanly in Python 3 (no 2to3)