Ronald Oussoren avatar Ronald Oussoren committed 940fe11

Updated protocol handling. It is no longer necessary to specify the list of
protocols defined by a class, the bridge will calculate this list based on the
methods implemented by a class.

Also fix the definition of a number of protocols.

This implements some more methods on NS{Mutable,}Dictionary to make it more
dict-like. The 'poseAsClass:' method is disabled because it crashes the brige due
to the implementation of that method in Objective-C. Given the other problems of
poseAs I don't think it would be usefull to fix this right now.

Comments (0)

Files changed (14)

pyobjc/Lib/AppKit/__init__.py

         _objc.selector(
             None, 
             selector='draggingEntered:',
-            signature='i@:@',
+            signature='I@:@',
             isRequired=0
         ),
         _objc.selector(
     ]
 )
 
+# Note: Apple's docs fro 'draggingSourceOperationMaskForLocal:' says that that
+# is the only required method in this protocol.
 NSDraggingSource = _objc.informal_protocol(
     'NSDraggingSource',
     [
             None, 
             selector='draggedImage:beganAt:',
             signature='v@:@{_NSPoint=ff}',
-            isRequired=1
+            isRequired=0
         ),
         _objc.selector(
             None, 
             selector='draggedImage:endedAt:deposited:',
             signature='v@:@{_NSPoint=ff}c',
-            isRequired=1
+            isRequired=0
         ),
         _objc.selector(
             None, 
             selector='draggedImage:endedAt:operation:',
             signature='v@:@{_NSPoint=ff}i',
-            isRequired=1
+            isRequired=0
         ),
         _objc.selector(
             None, 
             selector='draggedImage:movedTo:',
             signature='v@:@{_NSPoint=ff}',
-            isRequired=1
+            isRequired=0
         ),
         _objc.selector(
             None, 
             None, 
             selector='ignoreModifierKeysWhileDragging',
             signature='c@:',
-            isRequired=1
+            isRequired=0
         ),
         _objc.selector(
             None, 
             selector='namesOfPromisedFilesDroppedAtDestination:',
             signature='@@:@',
-            isRequired=1
+            isRequired=0
         ),
     ]
 )
             isRequired=1
         ),
     ],
-    warnIfUndeclared= 0 # There's little change of problems, and 
-                        # there's the issue of backward compatibility.
 )
 
 NSOutlineViewDelegate = _objc.informal_protocol(

pyobjc/Lib/Foundation/test/test_nsdictionary.py

 import unittest
 import objc
+import types
 
 from Foundation import *
 
 class TestNSDictionaryInteraction(unittest.TestCase):
+    def testMethods(self):
+        for nm in dir(types.DictType):
+            if nm.startswith('__'):
+                continue
+
+            if isinstance(getattr(types.DictType, nm), (types.BuiltinFunctionType, types.FunctionType)):
+                # Skip class methods, that needs more work in the core
+                continue
+
+            self.assert_(hasattr(NSMutableDictionary, nm), "NSMutableDictionary has no method '%s'"%(nm,))
+
     def testRepeatedAllocInit(self):
         for i in range(1,1000):
             d = NSDictionary.alloc().init()

pyobjc/Lib/objc/_convenience.py

     ('__delitem__', lambda self, key: self.removeObjectForKey_(key)), 
 )
 
+def dict_update(self, other):
+    for key, value in other.items():
+        self.setObject_forKey_(value, key)
+
+def dict_setdefault(self, key, dflt=None):
+    res = self.objectForKey_(key)
+    if res is None:
+        res = dflt
+        self.setObject_forKey_(dflt, key)
+    return res
+
+def dict_pop(self, key, dflt=None):
+    res = self.objectForKey_(key)
+    if res is None:
+        if dflt is None:
+            raise KeyError, key
+        res = dflt
+    else:
+        self.removeObjectForKey_(key)
+    return res
+
+
+def dict_popitem(self):
+    o = self.keyEnumerator().nextItem()
+    if o is None:
+        raise KeyError, "popitem on an empty dict"
+    v = self.objectForKey_(o)
+    if v is None:
+        raise KeyError, "popitem on an empty dict"
+    return (o, v)
+
 CONVENIENCE_METHODS['setObject:forKey:'] = (
     ('__setitem__', lambda self, key, value: self.setObject_forKey_(value, key)), 
+    ('update', dict_update),
+    ('setdefault', dict_setdefault),
+    ('pop', dict_pop),
+    ('popitem', dict_popitem),
 )
 
+
 CONVENIENCE_METHODS['count'] = (
     ('__len__', lambda self: self.count()),
 )
             raise IndexError, "index out of range"
     return self.objectAtIndex_(idx)
 
+CONVENIENCE_METHODS['addObject:'] = (
+    ( 'append', lambda self, item: self.addObject_(item) ),
+)
+
+CONVENIENCE_METHODS['addObjectsFromArray:'] = (
+    ('extend', lambda self, item: self.addObjectsFromArray_(item)),
+)
+
+def index_indexOfObject(self, item):
+    import Foundation
+
+    res = self.indexOfObject_(item)
+    if res == Foundation.NSNotFound:
+        raise ValueError, "NSArray.index(x): x not in list"
+
+CONVENIENCE_METHODS['indexOfObject:'] = (
+    ('index', index_indexOfObject),
+)
+
+CONVENIENCE_METHODS['insertObject:atIndex:'] = (
+    ( 'insert', lambda self, idx, item: self.insertObject_atIndex(item,idx)),
+)
+
 CONVENIENCE_METHODS['objectAtIndex:'] = (
     ('__getitem__', __getitem__objectAtIndex),
     ('__getslice__', __getitem__objectAtIndexWithSlice),
     values = aDict.objectsForKeys_notFoundMarker_(keys, runtime.NSNull.null())
     return zip(keys, values)
 
+
 CONVENIENCE_METHODS['allKeys'] = (
     ('keys', lambda self: self.allKeys()),
     ('items', lambda self: dictItems(self)),
     ('values', lambda self: self.allValues()),
 )
 
+def itemsGenerator(aDict):
+    anEnumerator = aDict.keyEnumerator()
+    nextObject = anEnumerator.nextObject()
+    while nextObject is not None:
+        yield (nextObject, aDict.objectForKey_(nextObject))
+        nextObject = anEnumerator.nextObject()
+
 CONVENIENCE_METHODS['keyEnumerator'] = (
     ('__iter__', lambda self: enumeratorGenerator(self.keyEnumerator())),
     ('iterkeys', lambda self: enumeratorGenerator( self.keyEnumerator())),
+    ('iteritems', lambda self: itemsGenerator(self)),
 )
 
 CONVENIENCE_METHODS['objectEnumerator'] = (
         selector(initWithObjects_forKeys_count_, signature='@@:^@^@i') ),
 )
 
+def UnsupportedMethod(self, *args):
+    raise ValueError, "Unsupported method"
+
+CONVENIENCE_METHODS['poseAsClass:'] = (
+    ('poseAsClass_', (UnsupportedMethod)),
+)

pyobjc/Lib/objc/test/test_posing.py

 #NSObject = objc.lookUpClass('NSObject')
 
 # Use a class that isn't used in the rest of the testsuite,
-# should write a native class for this!
-BaseClass = objc.lookUpClass('NSPortCoder')
+# should write a native class for this! NSPortCoder
+BaseName = 'NSPortCoder'
+BaseClass = objc.lookUpClass(BaseName)
 
 class TestPosing(unittest.TestCase):
     def testPosing(self):
         class PoseClass(BaseClass):
             __slots__ = ()  # Don't add instance variables, not even __dict__
-            def description(self):
-                return "<<subdescrip>> " + super.description()
+            def testPosingMethod(self):
+                return "<PoseClass instance>"
 
         PoseClass.poseAsClass_(BaseClass)
-        
-        obj = BaseClass.new()
+       
+        # Whoops, this is a problem: We keep referencing the old class!
+        #obj = objc.lookUpClass(BaseName).new()
+        obj = objc.runtime.__getattr__(BaseName).alloc().init()
+        self.assert_(isinstance(obj, PoseClass))
+        self.assertEquals(obj.testPosingMethod(), "<PoseClass instance>")
+        del obj
+
+
 
 if __name__ == '__main__':
     unittest.main()

pyobjc/Modules/objc/alloc_hack.m

 int
 PyObjC_InstallAllocHack(void)
 {
-	return ObjC_RegisterMethodMapping(
+	int r;
+
+	r = ObjC_RegisterMethodMapping(
 		objc_lookUpClass("NSObject"),
 		@selector(alloc),
 		call_NSObject_alloc,
 		(IMP)imp_NSObject_alloc);
+	if (r != 0) return r;
+
+	return r;
+
 }

pyobjc/Modules/objc/class-builder.m

 /*
  * When we create a 'Class' we actually create the struct below. This allows
  * us to add some extra information to the class defintion.
+ *
+ * NOTE1: the meta_class field is first because poseAs: copies the class but
+ *        not the meta class (on MacOS X <= 10.2)
+ * NOTE2: That doesn't help, test_posing still crashes.
  */
 #define MAGIC 0xDEADBEEF
-#define CHECK_MAGIC(o) do { if (((struct class_wrapper*)(o))->magic != MAGIC) abort(); } while(0)
+#define CLASS_WRAPPER(cls) ((struct class_wrapper*)(cls))
+#define CHECK_MAGIC(o) do { if (CLASS_WRAPPER(o)->magic != MAGIC) abort(); } while(0)
 struct class_wrapper {
-	struct objc_class  class;
-	struct objc_class  meta_class;
-	PyObject*          python_class;
+	struct objc_class class;
+	struct objc_class meta_class;
+	PyObject* python_class;
 	unsigned int magic; 
 };
 
 
 	CHECK_MAGIC(objc_class);
 
-	if (((struct class_wrapper*)objc_class)->python_class != NULL) {
+	if (CLASS_WRAPPER(objc_class)->python_class != NULL) {
 		ObjCErr_Set(ObjCExc_internal_error,
 			"Trying to set update PythonClass of %s",
 			objc_class->name);
 	}
 
 
-	((struct class_wrapper*)objc_class)->python_class = py_class;
+	CLASS_WRAPPER(objc_class)->python_class = py_class;
 	Py_INCREF(py_class);
 
 	objc_addClass(objc_class);
  */
 void PyObjCClass_UnbuildClass(Class objc_class)
 {
-	struct class_wrapper* wrapper = (struct class_wrapper*)objc_class;
+	struct class_wrapper* wrapper = CLASS_WRAPPER(objc_class); 
 
 	if (objc_class == nil) {
 		ObjCErr_Set(ObjCExc_internal_error, 
 		return;
 	}
 
-	CHECK_MAGIC(wrapper);
+	CHECK_MAGIC(objc_class);
 
 	if (wrapper->python_class != NULL) {
 		ObjCErr_Set(ObjCExc_internal_error,
 {
 	int len;
 	int i;
+	PyObject* proto;
+	PyObject* info;
 
 	if (!PyList_Check(protocols)) {
 		ObjCErr_Set(ObjCExc_internal_error,
 		return NULL;
 	}
 
-	len = PyList_Size(protocols);
+	/* First try the explicit protocol definitions */
+	len = PyList_GET_SIZE(protocols);
 	for (i = 0; i < len; i++) {
-		PyObject* p;
-		PyObject* info;
-	
-		p = PyList_GetItem(protocols, i);
-		if (p == NULL) {
+		proto = PyList_GET_ITEM(protocols, i);
+		if (proto == NULL) {
 			PyErr_Clear();
 			continue;
 		}
-		if (!PyObjCInformalProtocol_Check(p)) continue;
+		if (!PyObjCInformalProtocol_Check(proto)) continue;
 
-		info = PyObjCInformalProtocol_FindSelector(p, selector);
+		info = PyObjCInformalProtocol_FindSelector(proto, selector);
 		if (info != NULL) {
 			return ObjCSelector_Signature(info);
 		}
 	}
+
+	/* Then check if another protocol users this selector */
+	proto = PyObjCInformalProtocol_FindProtocol(selector);
+	if (proto == NULL) {
+		PyErr_Clear();
+		return NULL;
+	}
+
+	info = PyObjCInformalProtocol_FindSelector(proto, selector);
+	if (info != NULL) {
+		if (PyList_Append(protocols, proto) < 0) {
+			return NULL;
+		}
+		Py_INCREF(proto);
+		return ObjCSelector_Signature(info);
+	}
+	
 	return NULL;
 }
 
 	 * because it is impossible to remove the registration from the
 	 * objective-C runtime (at least on MacOS X).
 	 */
-	return (Class)new_class;
+	return &new_class->class;
 
 error_cleanup:
 	Py_XDECREF(py_superclass);

pyobjc/Modules/objc/informal-protocol.m

 proto_new(PyTypeObject* type __attribute__((__unused__)), 
 	PyObject* args, PyObject* kwds)
 {
-static	char*	keywords[] = { "name", "selectors", "warnIfUndeclared", NULL };
+static	char*	keywords[] = { "name", "selectors", NULL };
 	PyObjCInformalProtocol* result;
 	PyObject* name;
 	PyObject* selectors;
 	int       i, len;
-	int	  warnIfUndeclared = 1;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|i:informal_protocol",
-			keywords, &name, &selectors, &warnIfUndeclared)) { 
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO:informal_protocol",
+			keywords, &name, &selectors)) { 
 		return NULL;
 	}
 
 	result->name = name;
 	result->selectors = selectors;
 
-#if 1
-	if (warnIfUndeclared) {
-		len = PyTuple_Size(result->selectors);
-		for (i = 0; i < len; i++) {
-			if (!ObjCSelector_Check(
-					PyTuple_GET_ITEM(selectors, i))) {
-				PyErr_Format(PyExc_TypeError, 
-					"Item %d is not a selector", i);
-				Py_DECREF(result);
-				return NULL;
-			}
-		}
-
-		if (selToProtocolMapping == NULL) {
-			selToProtocolMapping = PyDict_New();
-			if (selToProtocolMapping == NULL) {
-				Py_DECREF(result);
-				return NULL;
-			}
-		}
-		for (i = 0; i < len; i++) {
-			ObjCSelector* tmp =
-				(ObjCSelector*)PyTuple_GET_ITEM(selectors, i);
-			
-			PyDict_SetItemString(selToProtocolMapping,
-				(char*)SELNAME(tmp->sel_selector),
-				name);
+	len = PyTuple_Size(result->selectors);
+	for (i = 0; i < len; i++) {
+		if (!ObjCSelector_Check(
+				PyTuple_GET_ITEM(selectors, i))) {
+			PyErr_Format(PyExc_TypeError, 
+				"Item %d is not a selector", i);
+			Py_DECREF(result);
+			return NULL;
 		}
 	}
-#endif
+
+	if (selToProtocolMapping == NULL) {
+		selToProtocolMapping = PyDict_New();
+		if (selToProtocolMapping == NULL) {
+			Py_DECREF(result);
+			return NULL;
+		}
+	}
+
+	for (i = 0; i < len; i++) {
+		ObjCSelector* tmp =
+			(ObjCSelector*)PyTuple_GET_ITEM(selectors, i);
+		
+		PyDict_SetItemString(selToProtocolMapping,
+			(char*)SELNAME(tmp->sel_selector),
+			(PyObject*)result);
+	}
 
 	Py_XINCREF(name);
 
 	return NULL;
 }
 
+static PyObject*
+FindSelInDict(PyObject* clsdict, SEL selector)
+{
+	PyObject* values;
+	PyObject* seq;
+	int       i, len;
+
+	values = PyDict_Values(clsdict);
+	if (values == NULL) {
+		return NULL;
+	}
+
+	seq = PySequence_Fast(values, "PyDict_Values result not a sequence");
+	if (seq == NULL) {
+		return NULL;
+	}
+	
+	len = PySequence_Fast_GET_SIZE(seq);
+	for (i = 0; i < len; i++) {
+		PyObject* v = PySequence_Fast_GET_ITEM(seq, i);
+		if (!ObjCSelector_Check(v)) continue;
+		if (ObjCSelector_Selector(v) == selector) {
+			Py_DECREF(seq);
+			Py_DECREF(values);
+			return v;
+		}
+	}
+	Py_DECREF(seq);
+	Py_DECREF(values);
+	return NULL;
+}
+
+static int signaturesEqual(char* sig1, char* sig2)
+{
+	char buf1[1024];
+	char buf2[1024];
+
+	/* Return 0 if the two signatures are not equal */
+	if (strcmp(sig1, sig2) == 0) return 1;
+
+	/* For some reason compiler-generated signatures contain numbers that
+	 * are not used by the runtime. These are irrelevant for our comparison
+	 */
+	simplify_signature(sig1, buf1, sizeof(buf1));
+	simplify_signature(sig2, buf2, sizeof(buf2));
+
+	return strcmp(buf1, buf2) == 0;
+}
+
 /*
  * Verify that 'cls' conforms to the informal protocol
  */
 int	
-PyObjCInformalProtocol_CheckClass(PyObject* obj, PyObject* cls)
+PyObjCInformalProtocol_CheckClass(
+	PyObject* obj, char* name, PyObject* super_class, PyObject* clsdict)
 {
 	PyObjCInformalProtocol* self = (PyObjCInformalProtocol*)obj;	
 	int i, len;
 			"First argument is not an objc.informal_protocol");
 		return 0;
 	}
-	if (!PyObjCClass_Check(cls)) {
+	if (!PyObjCClass_Check(super_class)) {
 		ObjCErr_Set(PyExc_TypeError, 
-			"Second argument is not an objc.objc_class");
+			"Third argument is not an objc.objc_class");
 		return 0;
 	}
+	if (!PyDict_Check(clsdict)) {
+		ObjCErr_Set(PyExc_TypeError, 
+			"Fourth argument is not a dict");
+		return 0;
+	}
+
 	seq = PySequence_Fast(self->selectors, "selector list not a sequence");
 	if (seq == NULL) {
 		return 0;
 
 	len = PySequence_Fast_GET_SIZE(seq);
 	for (i = 0; i < len; i++) {
+		SEL sel;
+		PyObject* m;
+
 		cur = PySequence_Fast_GET_ITEM(seq, i);
 		if (cur == NULL) {
 			continue;
 		}
 
-		if (ObjCSelector_Check(cur)) {
-			SEL sel = ObjCSelector_Selector(cur);
-			PyObject* m;
+		if (!ObjCSelector_Check(cur)) {
+			continue;
+		}
 
-			m = PyObjCClass_FindSelector(cls, sel);
-			if (m == NULL && ObjCSelector_Required(cur)) {
+		sel = ObjCSelector_Selector(cur);
+
+		m = FindSelInDict(clsdict, sel);
+		if (m == NULL) {
+			m = PyObjCClass_FindSelector(super_class, sel);
+		}
+
+		if (m == NULL || !ObjCSelector_Check(m)) {
+			if (ObjCSelector_Required(cur)) {
 				ObjCErr_Set(PyExc_TypeError,
-					"class %s does not implement protocol "
-					"%s: no implementation for %s",
-					((PyTypeObject*)cls)->tp_name,
+					"class %s does not fully implement "
+					  "protocol %s: no implementation for %s",
+					name,
 					PyString_AsString(self->name),
 					SELNAME(sel));
+					Py_DECREF(seq);
+				return 0;
+			} else {
+				PyErr_Clear();
+			}
+		} else {
+			if (!signaturesEqual(ObjCSelector_Signature(m),
+				ObjCSelector_Signature(cur)) != 0) {
+
+				ObjCErr_Set(PyExc_TypeError,
+					"class %s does not correctly implement "
+					  "protocol %s: "
+					  "the signature for method %s is "
+					  "%s instead of %s",
+					name,
+					PyString_AsString(self->name),
+					SELNAME(sel),
+					ObjCSelector_Signature(m),
+					ObjCSelector_Signature(cur)
+				);
 				Py_DECREF(seq);
 				return 0;
 			}
-			if (m) {
-				if (strcmp(ObjCSelector_Signature(m),
-					ObjCSelector_Signature(cur)) != 0) {
-
-					ObjCErr_Set(PyExc_TypeError,
-						"class %s does not implement "
-						"protocol %s: incorrect "
-						"signature for method %s",
-						((PyTypeObject*)cls)->tp_name,
-						PyString_AsString(self->name),
-						SELNAME(sel));
-					Py_DECREF(seq);
-					return 0;
-				}
-			} else {
-				PyErr_Clear();
-			}
 		}
 	}
 	Py_DECREF(seq);
 	return 1;
 }
 
+PyObject*
+PyObjCInformalProtocol_FindProtocol(SEL selector)
+{
+	if (selToProtocolMapping == NULL) return NULL;
+	PyObject* item;
 
-
-/*
- * Given the failure mode of most protocol problems it might be better to
- * just generate an exception.
- */
-int	
-PyObjCInformalProtocol_Warnings(char* name, PyObject* clsDict, PyObject* protocols)
-{
-	PyObject* seq;
-	int len, i;
-	PyObject* keys;
-	int  haveWarnings = 0;
-	PyObject* protoMap;
-
-	if (selToProtocolMapping == NULL) return 0;
-	
-	protoMap = PyDict_New();
-	if (protoMap == NULL) {
-		return -1;
+	item = PyDict_GetItemString(selToProtocolMapping, SELNAME(selector));
+	if (item != NULL) {
+		return item;
 	}
 
-	if (!PyDict_Check(clsDict)) {
-		PyErr_SetString(PyExc_TypeError, 
-			"class dict is not a dictionary");
-		Py_DECREF(protoMap);
-		return -1;
-	}
-		
-
-	/*
-	 * protoMap will contain the protocol names as keys, this makes 
-	 * checking protocols easier.
-	 */
-	seq = PySequence_Fast(protocols, "protocol list is not a sequence");
-	if (seq == NULL) {
-		Py_DECREF(protoMap);
-		return -1;
-	}
-
-	len = PySequence_Fast_GET_SIZE(seq);
-	for (i = 0;i < len; i++) {
-		PyObjCInformalProtocol* obj =
-			(PyObjCInformalProtocol*)PySequence_Fast_GET_ITEM(
-				seq, i);
-		if (PyDict_SetItem(protoMap,  obj->name, (PyObject*)obj) < 0) {
-			Py_DECREF(seq);
-			Py_DECREF(protoMap);
-			return -1;
-		}  else {
-			Py_INCREF(obj->name);
-			Py_INCREF(obj);
-		}
-	}
-	Py_DECREF(seq);
-	seq = NULL;
-
-	/*
-	 * Actually perform the check.
-	 */
-	keys = PyDict_Keys(clsDict);
-	if (keys == NULL) {
-		Py_DECREF(protoMap);
-		return -1;
-	}
-
-	seq = PySequence_Fast(keys, "Dict keys not a sequence!?");
-	Py_DECREF(keys); keys = NULL;
-	if (seq == NULL) {
-		Py_DECREF(protoMap);
-		return -1;
-	}
-
-	len = PySequence_Fast_GET_SIZE(seq);
-	for (i = 0;i < len; i++) {
-		PyObject* o = PySequence_Fast_GET_ITEM(seq, i);
-		PyObject* p;
-		PyObject* q;
-
-		q = PyDict_GetItem(clsDict, o);
-		if (q == NULL) {
-			PyErr_Clear();
-			continue;
-		}
-
-		if (!ObjCSelector_Check(q)) {
-			continue;
-		}
-
-		p = PyDict_GetItemString(selToProtocolMapping,
-			(char*)SELNAME(((ObjCSelector*)q)->sel_selector));
-		if (p == NULL) {
-			PyErr_Clear();
-			continue;
-		}
-
-		if ((q = PyDict_GetItem(protoMap, p)) == NULL) {
-			/* Oops, we seem to be implementing a protocol
-			 * without saying it.
-			 */
-			 char buf[1024];
-
-			 snprintf(buf, sizeof(buf),
-			 	"Class %s is implementing part of protocol %s "
-				"without declaring this (method %s)",
-				name, PyString_AS_STRING(p),
-				PyString_AS_STRING(o));
-			 haveWarnings = 1;
-			 PyErr_Warn(PyObjCExc_ProtocolWarning, buf);
-			 if (PyErr_Occurred()) {
-				Py_DECREF(seq);
-			 	Py_DECREF(protoMap);
-				return -1;
-			 }
-		}
-	}
-	Py_DECREF(seq);
-
-	Py_DECREF(protoMap);
-	return 0;
+	PyErr_Clear();
+	return NULL;
 }

pyobjc/Modules/objc/objc-class.m

 	int       len;
 	Class      objc_class = NULL;
 	Class	   super_class = NULL;
+	PyObject*  py_super_class = NULL;
 	PyObjC_class_info* info;
 	PyObject* protocols;
 	PyObject* real_bases;
 				"be objective-C based");
 		return NULL;
 	}
-	super_class = PyObjCClass_GetClass(v);
+	py_super_class = v;
+	super_class = PyObjCClass_GetClass(py_super_class);
 	if (super_class) {
-		PyObjCClass_CheckMethodList(v);
+		PyObjCClass_CheckMethodList(py_super_class);
 	}
 
+	/* TODO: Make list available through __pyobjc_protocols__ */
 	protocols = PyList_New(0);
 	if (protocols == NULL) return NULL;
+
 	real_bases = PyList_New(0);
 	if (real_bases == NULL) {
 		Py_DECREF(protocols);
 		return NULL;
 	}
 
-#if 1
-	if (PyObjCInformalProtocol_Warnings(name, dict, protocols) < 0) {
-		PyObjCClass_UnbuildClass(objc_class);
-		Py_DECREF(protocols);
-		Py_DECREF(real_bases);
-		return NULL;
+	/* Verify that the class conforms to all protocols it claims to 
+	 * conform to.
+	 */
+	len = PyList_Size(protocols);
+	for (i = 0; i < len; i++) {
+		PyObject* p = PyList_GetItem(protocols, i);
+
+		if (p == NULL) {
+			PyErr_Clear();
+			continue;
+		}
+
+		if (!PyObjCInformalProtocol_Check(p)) {
+			continue;
+		}
+
+		if (!PyObjCInformalProtocol_CheckClass(
+					p, name, py_super_class, dict)) {
+			Py_DECREF(real_bases);
+			Py_DECREF(protocols);
+			PyObjCClass_UnbuildClass(objc_class);
+			return NULL;
+		}
 	}
-#endif
 
 	delmethod = PyDict_GetItemString(dict, "__del__");
 	if (delmethod == NULL) {
 	args = NULL;
 	real_bases = NULL;
 
-	/* Verify that the class conforms to all protocols it claims to 
-	 * conform to.
-	 */
-	len = PyList_Size(protocols);
-	for (i = 0; i < len; i++) {
-		PyObject* p = PyList_GetItem(protocols, i);
-
-		if (p == NULL) {
-			PyErr_Clear();
-			continue;
-		}
-
-		if (PyObjCInformalProtocol_Check(p)) {
-			/* This doesn't work: Cannot dealloc 'res'! */
-			if (!PyObjCInformalProtocol_CheckClass(p, res)) {
-				/*
-				 * FIXME!
-				Py_DECREF(res);
-				 */
-				Py_DECREF(protocols);
-				PyObjCClass_UnbuildClass(objc_class);
-				return NULL;
-			}
-		}
-	}
 	
 	Py_DECREF(protocols);
 	protocols = NULL;

pyobjc/Modules/objc/objc_support.h

 
 extern struct objc_method_list *objc_allocMethodList(int numMethods);
 
+/* This one is implemented in super-call.m, should be moved and renamed */
+extern void simplify_signature(char* signature, char* buf, size_t buflen);
+
+
 #endif /* _objc_support_H */

pyobjc/Modules/objc/pyobjc.h

 extern PyTypeObject PyObjCInformalProtocol_Type;
 #define PyObjCInformalProtocol_Check(obj) PyObject_TypeCheck(obj, &PyObjCInformalProtocol_Type)
 
-int     PyObjCInformalProtocol_CheckClass(PyObject* obj, PyObject* cls);
+int PyObjCInformalProtocol_CheckClass(PyObject*, char*, PyObject*, PyObject*);
 PyObject* PyObjCInformalProtocol_FindSelector(PyObject* obj, SEL selector);
 int PyObjCInformalProtocol_Warnings(char* name, PyObject* clsdict, PyObject* protocols);
+PyObject* PyObjCInformalProtocol_FindProtocol(SEL selector);
 
 
 /* See alloc_hack.m */

pyobjc/Modules/objc/super-call.m

  * do this. objc_support doesn't work correctly with (structs containing) 
  * bitfields, but neither does NSMethodSignature.
  */
-static void
+void
 simplify_signature(char* signature, char* buf, size_t buflen)
 {
 	int                i, argcount;

pyobjc/Modules/objc/toll-free-bridging.m

 	int r;
 	id  val;
 
+#if PY_VERSION_HEX >= 0x020300B1 
+
+	r = CFObj_Convert(argument, (CFTypeRef*)&val);
+	if (r) return val;
+	PyErr_Clear();
+	return NULL;
+
+#else
 	r = CFTypeRefObj_Convert(argument, (CFTypeRef*)&val);
 	if (r) return val;
 
 
 	PyErr_Clear();
 	return NULL;
+#endif
 }
 
 PyObject* PyObjC_IDToCFType(id argument)
 {
+#if PY_VERSION_HEX >= 0x020300B1 
+	return CFObj_New((CFTypeRef)argument);
+
+#else
 	if ([argument isKindOfClass:[NSMutableString class]]) {
 		return CFMutableStringRefObj_New((CFMutableStringRef)argument);
 	}
 	 * generic one.
 	 */
 	return CFTypeRefObj_New((CFTypeRef)argument);
+#endif 
 }
 
 
   expire as soon as the last reference from Python died, *not* when the 
   Objective-C object died.
 
-- We now generate warnings if a class implements an informal protocol, but
-  doesn't declare that in its definition.
-
-  TODO: Use the protocol-list to automaticly deduce the protocols implemented
-  by a class.
+- It is no longer necessary to specify which protocols are implemented by
+  a class, this information is automaticly deduced from the list of implemented
+  methods. You'll still a runtime error if you implement some methods of a protocol
+  and one of the unimplemented methods is required.
 
 Version 0.9 (May-02-2003):
 - This version includes numerous bugfixes and improvements.
         #"-pedantic",
 
         "-Wno-import", 
-        "-O2", "-g",
+        "-O0", "-g",
         #"-Werror",
         ]
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.