Commits

Bill Bumgarner  committed 4ba7445

Added classAddMethod() -- with testing. It allows the developer to add a method to any class under a different name than the one specified in the method object itself.

Starting to add Key/Value coding support.

  • Participants
  • Parent commits 1ab6214

Comments (0)

Files changed (5)

File pyobjc/Lib/objc/test/test_methodedits.py

         self.assertEquals(newInstance.newSubMethod(), "<new-method-sub>")
         self.assertEquals(preEverythingInstance.newSubMethod(), "<new-method-sub>")
 
+class TestAddMethodWithNewName(unittest.TestCase):
+    def setUp(self):
+        self.NSObjectClass = MEClass
+
+    def testAddMethodWithNameName(self):
+        objc.classAddMethod(self.NSObjectClass, "doTheFoo", MethodsSub.newMethod)
+        objc.classAddMethod(self.NSObjectClass, "doTheBoo", MethodsSub.newSubMethod)
+
+        self.assert_(self.NSObjectClass.instancesRespondToSelector_("doTheFoo"))
+        self.assert_(self.NSObjectClass.instancesRespondToSelector_("doTheBoo"))
+
+        newInstance = self.NSObjectClass.new()
+        
+        self.assertEquals(newInstance.doTheFoo(), "<sub-new-method>")
+        self.assertEquals(preEverythingInstance.doTheFoo(), "<sub-new-method>")
+        self.assertEquals(newInstance.doTheBoo(), "<new-method-sub>")
+        self.assertEquals(preEverythingInstance.doTheBoo(), "<new-method-sub>")
+
 class TestFromPythonClassToObjCClass(unittest.TestCase):
     def setUp(self):
         self.NSObjectClass = objc.runtime.NSObject

File pyobjc/Modules/objc/OC_PythonObject.h

 - (BOOL) respondsToSelector:(SEL) aSelector;
 - (NSMethodSignature *) methodSignatureForSelector:(SEL) selector;
 - (void) doesNotRecognizeSelector:(SEL) aSelector;
-
 @end /* OC_PythonObject class interface */
 
 #endif /* _OC_PythonObject_H */

File pyobjc/Modules/objc/OC_PythonObject.m

 	Py_INCREF(pyObject);
 	return pyObject;
 }
-
 @end /* OC_PythonObject class implementation */

File pyobjc/Modules/objc/module.m

 	return PyObjCClass_New(objc_class);
 }
 
+PyDoc_STRVAR(classAddMethod_doc,
+	     "classAddMethod(targetClass, methodName, method)\n"
+	     "\n"
+	     "Adds method to targetClass with methodName as the name.  If methodName is None, name of method will be extraded from method in the same fashion as classAddMethods().");
+
+static PyObject*
+classAddMethod(PyObject* self __attribute__((__unused__)), 
+	PyObject* args, PyObject* keywds)
+{
+	static 	char* kwlist[] = { "targetClass", "methodName", "method", NULL };
+	PyObject* classObject = NULL;
+	char* methodName = NULL;
+	int methodNameSize = 0;
+	PyObject* method = NULL;
+	Class targetClass;
+	struct objc_method_list *methodsToAdd;
+
+	if (!PyArg_ParseTupleAndKeywords(args, keywds, 
+			"Oz#O:classAddMethod", kwlist,
+			&classObject, &methodName, &methodNameSize, &method)) {
+		return NULL;
+	}
+
+	targetClass  = PyObjCClass_GetClass(classObject);
+	methodsToAdd = objc_allocMethodList(1);
+	if (methodsToAdd == NULL) {
+	    PyErr_NoMemory();
+	    return NULL;
+	}
+
+	methodsToAdd->method_count = 1;
+
+	struct objc_method *objcMethod;
+	objcMethod = &methodsToAdd->method_list[0];
+
+	/* check
+	 * FIXME: We should support functions here, just like with
+	 * class definitions.
+	 */
+	if (!PyObjCSelector_Check(method)) {
+	    PyErr_SetString(PyExc_TypeError,
+			    "All objects in methodArray must be of type "
+			    "<objc.selector>.");
+	    goto cleanup_and_return_error;
+	}
+
+	/* install in methods to add */
+	if ( (methodName != NULL) && (methodNameSize > 0) ) {
+	    SEL aName = sel_getUid(methodName);
+	    if (aName == NULL)
+		aName = sel_registerName(methodName);
+	    if (aName == NULL) {
+		PyErr_SetString(PyExc_TypeError,
+				"Failed to register SEL.");
+		goto cleanup_and_return_error;
+	    }
+	    objcMethod->method_name = aName;
+	} else
+	    objcMethod->method_name = PyObjCSelector_Selector(method);
+	objcMethod->method_types = strdup(PyObjCSelector_Signature(method));
+	objcMethod->method_imp = ObjC_MakeIMPForPyObjCSelector((PyObjCSelector*)method);
+
+	/* add the methods */
+	class_addMethods(targetClass, methodsToAdd);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+
+cleanup_and_return_error:
+	if (methodsToAdd) free(methodsToAdd);
+	return NULL;
+}
+
 PyDoc_STRVAR(classAddMethods_doc,
 	     "classAddMethods(targetClass, methodsArray)\n"
 	     "\n"
 	  lookUpClass_doc
 	},
 	{
+	  "classAddMethod",
+	  (PyCFunction)classAddMethod,
+	  METH_VARARGS|METH_KEYWORDS,
+	  classAddMethod_doc
+	},
+	{
 	  "classAddMethods",
 	  (PyCFunction)classAddMethods,
 	  METH_VARARGS|METH_KEYWORDS,

File pyobjc/Modules/objc/objc-class.m

 	 * semantics.
 	 */
 	if (objc_class->ivars) {
+	    int i;
+	    struct objc_ivar *var;
 		for (i = 0; i < objc_class->ivars->ivar_count; i++) {
 			var = objc_class->ivars->ivar_list + i;