[PyObjC-svn] r2263 - trunk/pyobjc/pyobjc-core/Modules/objc

[email protected] Sat, 11 Jul 2009 04:09:20 -0500
Newsgroups gmane.comp.python.pyobjc.cvs
Message-ID <[email protected]>
Author: ronaldoussoren
Date: Sat Jul 11 04:09:20 2009
New Revision: 2263

Log:
Fix issue where KVC could result in an infinite recursion loop.


Modified:
   trunk/pyobjc/pyobjc-core/Modules/objc/class-builder.m
   trunk/pyobjc/pyobjc-core/Modules/objc/objc-object.m

Modified: trunk/pyobjc/pyobjc-core/Modules/objc/class-builder.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/class-builder.m	(original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/class-builder.m	Sat Jul 11 04:09:20 2009
@@ -2093,8 +2093,16 @@
 		objc_superSetReceiver(spr, self);
 		*((id *)retval) = (id)objc_msgSendSuper(&spr, _meth, key);
 	NS_HANDLER
+
 		/* Parent doesn't know the key, try to create in the 
 		 * python side, just like for plain python objects.
+		 *
+		 * NOTE: We have to be extermely careful in here, some classes,
+		 * like NSManagedContext convert __getattr__ into a -valueForKey:,
+		 * and that can cause infinite loops.
+		 *
+		 * This is why attribute access is hardcoded using PyObjCObject_GetAttrString
+		 * rather than PyObject_GetAttrString.
 		 */
 		if (([[localException name] isEqual:@"NSUnknownKeyException"]
 			) && [[self class] accessInstanceVariablesDirectly]) {
@@ -2104,10 +2112,10 @@
 			PyObject *res = NULL;
 			r = -1;
 			do {
-				res = PyObject_GetAttrString(selfObj, (char *)[key UTF8String]);
+				res = PyObjCObject_GetAttrString(selfObj, (char *)[key UTF8String]);
 				if (res == NULL) {
 					PyErr_Clear();
-					res = PyObject_GetAttrString(selfObj, (char *)[[@"_" stringByAppendingString:key] UTF8String]);
+					res = PyObjCObject_GetAttrString(selfObj, (char *)[[@"_" stringByAppendingString:key] UTF8String]);
 					if (res == NULL) {
 						break;
 					}

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 Jul 11 04:09:20 2009
@@ -272,6 +272,7 @@
 }
 
 
+
 static PyObject *
 object_getattro(PyObject *obj, PyObject * volatile name)
 {
@@ -947,3 +948,19 @@
 			((PyObjCObject*)object)->objc_object, object);
 	((PyObjCObject*)object)->objc_object = nil;
 }
+
+PyObject* PyObjCObject_GetAttr(PyObject* obj, PyObject* name)
+{
+	return object_getattro(obj, name);
+}
+
+
+PyObject* PyObjCObject_GetAttrString(PyObject* obj, char* name)
+{
+	PyObject* pyname = PyString_FromString(name);
+	if (pyname == NULL) return NULL;
+
+	PyObject* rv = object_getattro(obj, pyname);
+	Py_DECREF(pyname);
+	return rv;
+}

------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge  
This is your chance to win up to $100,000 in prizes! For a limited time, 
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize  
details at: http://p.sf.net/sfu/Challenge