[PyObjC-svn] r2472 - in trunk/pyobjc/pyobjc-core: . Lib/objc Modules/objc PyObjCTest libffi-src/tests/testsuite/libffi.call

[email protected] Sat, 08 May 2010 15:22:54 -0500
Newsgroups gmane.comp.python.pyobjc.cvs
Message-ID <[email protected]>
Author: ronaldoussoren
Date: Sat May  8 15:22:54 2010
New Revision: 2472

Log:
Implement a large subset of the set()/frozenset() API.


Added:
   trunk/pyobjc/pyobjc-core/PyObjCTest/test_set_interface.py   (contents, props changed)
Modified:
   trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py
   trunk/pyobjc/pyobjc-core/Modules/objc/objc-object.m
   trunk/pyobjc/pyobjc-core/Modules/objc/objc_util.m
   trunk/pyobjc/pyobjc-core/NEWS.txt
   trunk/pyobjc/pyobjc-core/libffi-src/tests/testsuite/libffi.call/ffitest.h

Modified: trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py	(original)
+++ trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py	Sat May  8 15:22:54 2010
@@ -974,6 +974,39 @@
 
         return result
 
+    def dict_new(cls, args, kwds):
+        if len(args) == 0:
+            pass
+
+        elif len(args) == 1:
+            d = dict()
+            for k , v in args[0]:
+                d[container_wrap(k)] = container_wrap(v)
+
+            for k, v in kwds.iteritems():
+                d[container_wrap(k)] = container_wrap(v)
+
+            return cls.dictionaryWithDictionary_(d)
+
+        else:
+            raise TypeError(
+                    "dict expected at most 1 arguments, got {0}".format(
+                        len(args)))
+        if kwds:
+            d = dict()
+            for k, v in kwds.iteritems():
+                d[container_wrap(k)] = container_wrap(v)
+
+            return cls.dictionaryWithDictionary_(d)
+
+        return cls.dictionary()
+
+    def nsdict_new(cls, *args, **kwds):
+        return dict_new(NSDictionary, args, kwds)
+
+    def nsmutabledict_new(cls, *args, **kwds):
+        return dict_new(NSMutableDictionary, args, kwds)
+
     if sys.version_info[0] == 3:
         CLASS_METHODS['NSDictionary'] = (
             ('__new__', nsdict_new),
@@ -984,7 +1017,7 @@
         )
 
         CLASS_METHODS['NSMutableDictionary'] = (
-            ('__new__', nsdict_new),
+            ('__new__', nsmutabledict_new),
             ('fromkeys', classmethod(nsmutabledict_fromkeys)),
         )
 
@@ -1042,32 +1075,6 @@
     return result
 
 
-def nsdict_new(cls, *args, **kwds):
-    if len(args) == 0:
-        pass
-
-    elif len(args) == 1:
-        d = dict()
-        for k , v in args[0]:
-            d[container_wrap(k)] = container_wrap(v)
-
-        for k, v in kwds.iteritems():
-            d[container_wrap(k)] = container_wrap(v)
-
-        return cls.dictionaryWithDictionary_(d)
-
-    else:
-        raise TypeError(
-                "dict expected at most 1 arguments, got {0}".format(
-                    len(args)))
-    if kwds:
-        d = dict()
-        for k, v in kwds.iteritems():
-            d[container_wrap(k)] = container_wrap(v)
-
-        return cls.dictionaryWithDictionary_(d)
-
-    return cls.dictionary()
 
 def nsarray_new(cls, sequence=None):
     if not sequence:
@@ -1112,3 +1119,210 @@
 NSMutableArray.__new__ = nsmutablearray_new
 NSMutableArray.alloc().init()
 #NSMutableSet.set()
+
+NSSet = lookUpClass('NSSet')
+NSMutableSet = lookUpClass('NSMutableSet')
+
+try:
+    from collections import Set
+    Set.register(NSSet)
+except:
+    Set = (set, frozenset, NSSet)
+
+def nsset_isdisjoint(self, other):
+    for item in self:
+        if item in other:
+            return False
+    return True
+
+def nsset_union(self, *other):
+    result = self.mutableCopy()
+    for val in other:
+        if isinstance(val, Set):
+            result.unionSet_(val)
+        else:
+            result.unionSet_(set(val))
+    return result
+
+def nsset_intersection(self, *others):
+    if len(others) == 0:
+        return self.mutableCopy()
+    result = NSMutableSet()
+    for item in self:
+        for o in others:
+            if item not in o:
+                break
+        else:
+            result.add(item)
+    return result
+
+def nsset_difference(self, *others):
+    result = self.mutableCopy()
+
+    for value in others:
+        if isinstance(value, Set):
+            result.minusSet_(value)
+        else:
+            result.minusSet_(set(value))
+
+    return result
+
+def nsset_symmetric_difference(self, other):
+    result = set()
+    for item in self:
+        if item not in other:
+            result.add(item)
+    for item in other:
+        if item not in self:
+            result.add(item)
+    return NSMutableSet(result)
+    
+
+def nsset__contains__(self, value):
+    hash(value) # Force error for non-hashable values
+    return self.containsObject_(value)
+
+def nsset__or__(self, other):
+    if not isinstance(self, Set):
+        raise TypeError("NSSet|value where value is not a set")
+    if not isinstance(other, 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, Set):
+        raise TypeError("value|NSSet where value is not a set")
+    if not isinstance(other, 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, Set):
+        raise TypeError("NSSet&value where value is not a set")
+    if not isinstance(other, 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, Set):
+        raise TypeError("value&NSSet where value is not a set")
+    if not isinstance(other, 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, Set):
+        raise TypeError("NSSet-value where value is not a set")
+    if not isinstance(other, 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, Set):
+        raise TypeError("NSSet-value where value is not a set")
+    if not isinstance(other, Set):
+        raise TypeError("NSSet-value where value is not a set")
+    return nsset_difference(other, self)
+
+def nsset__xor__(self, other):
+    if not isinstance(self, Set):
+        raise TypeError("NSSet-value where value is not a set")
+    if not isinstance(other, Set):
+        raise TypeError("NSSet-value where value is not a set")
+    return nsset_symmetric_difference(other, self)
+
+def nsset_issubset(self, other):
+    return self.isSubsetOfSet_(other)
+
+def nsset__eq__(self, other):
+    if not isinstance(other, Set):
+        return False
+
+    return self.isEqualToSet_(other)
+
+def nsset__ne__(self, other):
+    if not isinstance(other, Set):
+        return True
+
+    return not self.isEqualToSet_(other)
+
+def nsset__lt__(self, other):
+    return (self <= other) and (self != other)
+
+def nsset_issuperset(self, other):
+    for item in other:
+        if item not in self:
+            return False
+
+    return True
+
+def nsset__gt__(self, other):
+    return (self >= other) and (self != other)
+
+if sys.version_info[0] == 2:
+    def nsset__cmp__(self, other):
+        try:
+            if self < other:
+                return -1
+            elif self == other:
+                return 0
+            else:
+                return 1
+        except TypeError:
+            return cmp(id(self), id(other))
+
+
+CLASS_METHODS['NSSet'] = (
+    ('__contains__',  nsset__contains__),
+    ('add',  lambda self, value: self.addObject_(value)),
+    ('isdisjoint',  nsset_isdisjoint),
+    ('union',  nsset_union),
+    ('intersection',  nsset_intersection),
+    ('difference',  nsset_difference),
+    ('symmetric_difference',  nsset_symmetric_difference),
+    ('issubset', nsset_issubset),
+    ('__eq__', nsset__eq__),
+    ('__ne__', nsset__ne__),
+    ('__le__', nsset_issubset),
+    ('__lt__', nsset__lt__),
+    ('issuperset', nsset_issuperset),
+    ('__ge__', nsset_issuperset),
+    ('__gt__', nsset__gt__),
+    ('__or__', nsset__or__),
+    ('__ror__', nsset__ror__),
+    ('__and__', nsset__and__),
+    ('__rand__', nsset__rand__),
+    ('__xor__', nsset__xor__),
+    ('__rxor__', nsset__xor__),
+    ('__sub__', nsset__sub__),
+)
+
+if sys.version_info[0] == 2:
+    CLASS_METHODS['NSSet'] += (
+        ('__cmp__', 'nsset__cmp__'),
+    )
+
+def nsset_new(cls, sequence=None):
+    if not sequence:
+        return NSSet.set()
+
+    if isinstance(sequence, (NSSet, set, frozenset)):
+        return NSSet.set().setByAddingObjectsFromSet_(sequence)
+
+    else:
+        return NSSet.set().setByAddingObjectsFromSet_(set(sequence))
+
+def nsmutableset_new(cls, sequence=None):
+    if not sequence:
+        return NSMutableSet.set()
+
+    if isinstance(sequence, (NSSet, set, frozenset)):
+        return NSMutableSet.set().setByAddingObjectsFromSet_(sequence)
+
+    else:
+        return NSMutableSet.set().setByAddingObjectsFromSet_(set(sequence))
+
+NSSet.__new__ = nsset_new
+NSMutableSet.__new__ = nsmutableset_new
+
+NSMutableSet.alloc().init()

Modified: trunk/pyobjc/pyobjc-core/Modules/objc/objc-object.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/objc-object.m	(original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/objc-object.m	Sat May  8 15:22:54 2010
@@ -284,7 +284,9 @@
 }
 
 
-
+void break_point(void) {
+	printf("break here\n");
+}
 static PyObject *
 object_getattro(PyObject *obj, PyObject * volatile name)
 {
@@ -317,7 +319,11 @@
 	}
 
 
+
 	namestr = PyBytes_AsString(bytes);
+	if (strcmp(namestr, "_attributeWithoutModel") == 0) {
+		break_point();
+	}
 	if (namestr == NULL) {
 		if (!PyErr_Occurred()) {
 			PyErr_SetString(PyExc_ValueError, "Empty name");

Modified: trunk/pyobjc/pyobjc-core/Modules/objc/objc_util.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/objc_util.m	(original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/objc_util.m	Sat May  8 15:22:54 2010
@@ -180,9 +180,14 @@
 		}
 	}
 #else
-	 buf = PyText_FromFormat("%s - %s", 
-               [[localException name] UTF8String],
-               [[localException reason] UTF8String]);
+	if ([[localException reason] UTF8String]) {
+		 buf = PyText_FromFormat("%s - %s", 
+		       [[localException name] UTF8String],
+		       [[localException reason] UTF8String]);
+	} else {
+		 buf = PyText_FromFormat("%s", 
+		       [[localException name] UTF8String]);
+	}
 	PyErr_SetObject(exception, buf);
 #endif
 	PyErr_Fetch(&exc_type, &exc_value, &exc_traceback);

Modified: trunk/pyobjc/pyobjc-core/NEWS.txt
==============================================================================
--- trunk/pyobjc/pyobjc-core/NEWS.txt	(original)
+++ trunk/pyobjc/pyobjc-core/NEWS.txt	Sat May  8 15:22:54 2010
@@ -23,11 +23,24 @@
   * ``NSDictionary.copy`` always returns an immutable dictionary, use
     ``NSDictionary.mutableCopy`` to get a mutable dictionary.
 
+  * Instances of ``NSDictionary`` cannot be pickled
+
   ``NSDictionary`` implements one important feature that native Python
   dictionaries don't: full support for Key-Value Observations. Sadly enough
   it is not possible to support Key-Value Observation of native Python 
   dictionaries without patching the interpreter.
 
+- NSSet and NSMutableSet implement the same interface as ``frozenset`` and
+  ``set``, except for the differences listed below:
+
+  * ``NSSet.copy`` and ``NSMutableSet.copy`` always return an immutable
+     object,  use the ``mutableCopy`` method to create a mutable copy.
+
+  * Instances of ``NSSet`` cannot be pickled
+
+  FIXME: This is currently tested using ``TestJointOps`` from the stdlib 
+  testset, add the other set related tests as well.
+
 - BUGFIX: accessing methods through ``anObject.pyobjc_instancMethods`` is
   now safer, before this release this could cause unlimited recursion
   (although I'm not sure if it was possible to trigger this without

Modified: trunk/pyobjc/pyobjc-core/libffi-src/tests/testsuite/libffi.call/ffitest.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/libffi-src/tests/testsuite/libffi.call/ffitest.h	(original)
+++ trunk/pyobjc/pyobjc-core/libffi-src/tests/testsuite/libffi.call/ffitest.h	Sat May  8 15:22:54 2010
@@ -9,7 +9,6 @@
 
 #define CHECK(x) !(x) ? abort() : 0
 
-
 /* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
    file open.  */
 #ifdef HAVE_MMAP_ANON

------------------------------------------------------------------------------