[PyObjC-svn] r2415 - in trunk/pyobjc/pyobjc-core: . Modules/objc PyObjCTest
[email protected] Tue, 23 Mar 2010 16:08:38 -0500
| Newsgroups | gmane.comp.python.pyobjc.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: ronaldoussoren
Date: Tue Mar 23 16:08:37 2010
New Revision: 2415
Log:
Improve test coverage for hidden selectors, and
fix most issues uncovered by them.
Modified:
trunk/pyobjc/pyobjc-core/Modules/objc/class-builder.h
trunk/pyobjc/pyobjc-core/Modules/objc/class-builder.m
trunk/pyobjc/pyobjc-core/Modules/objc/module.m
trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.h
trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.m
trunk/pyobjc/pyobjc-core/Modules/objc/selector.h
trunk/pyobjc/pyobjc-core/Modules/objc/selector.m
trunk/pyobjc/pyobjc-core/NEWS.txt
trunk/pyobjc/pyobjc-core/PyObjCTest/test_hidden_selector.py
trunk/pyobjc/pyobjc-core/PyObjCTest/test_methodedits.py
trunk/pyobjc/pyobjc-core/setup.py
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/class-builder.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/class-builder.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/class-builder.h Tue Mar 23 16:08:37 2010
@@ -9,7 +9,8 @@
char* name,
PyObject* class_dict,
PyObject* meta_dict,
- PyObject* hiddenSelectors);
+ PyObject* hiddenSelectors,
+ PyObject* hiddenClassSelectors);
int PyObjCClass_UnbuildClass(Class new_class);
int PyObjCClass_FinishClass(Class objc_class);
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 Tue Mar 23 16:08:37 2010
@@ -168,7 +168,7 @@
* is already registered with the Objective-C runtime.
*/
int
-PyObjCClass_UnbuildClass(Class objc_class)
+PyObjCClass_UnbuildClass(Class objc_class __attribute__((__unused__)))
{
PyObjC_Assert(objc_class != nil, -1);
PyObjC_Assert(objc_lookUpClass(class_getName(objc_class)) == nil, -1);
@@ -611,7 +611,7 @@
Class
PyObjCClass_BuildClass(Class super_class, PyObject* protocols,
char* name, PyObject* class_dict, PyObject* meta_dict,
- PyObject* hiddenSelectors)
+ PyObject* hiddenSelectors, PyObject* hiddenClassSelectors)
{
PyObject* seq;
PyObject* key_list = NULL;
@@ -1005,6 +1005,15 @@
goto error_cleanup;
}
+
+ if (!PyObjCSelector_IsHidden(value)) {
+ if (PyDict_SetItem(meta_dict, key, value) == -1) {
+ goto error_cleanup;
+ }
+ } else {
+ shouldCopy = NO;
+ }
+
if (shouldCopy) {
r = PyDict_SetItem(meta_dict, pyname, value);
Py_DECREF(pyname);
@@ -1012,14 +1021,21 @@
goto error_cleanup;
}
}
- if (PyDict_SetItem(meta_dict, key, value) == -1) {
- goto error_cleanup;
- }
if (PyDict_DelItem(class_dict, key) == -1) {
goto error_cleanup;
}
} else {
r = PySet_Add(instance_methods, value);
+ if (r == -1) {
+ goto error_cleanup;
+ }
+ if (PyObjCSelector_IsHidden(value)) {
+ r = PyDict_DelItem(class_dict, key);
+ if (r == -1) {
+ goto error_cleanup;
+ }
+ shouldCopy = NO;
+ }
if (shouldCopy) {
r = PyDict_SetItem(class_dict, pyname, value);
Py_DECREF(pyname);
@@ -1087,8 +1103,10 @@
if (PyObjCSelector_IsClassMethod(value)) {
- if (PyDict_SetItem(meta_dict, key, value) == -1) {
- goto error_cleanup;
+ if (!PyObjCSelector_IsHidden(value)) {
+ if (PyDict_SetItem(meta_dict, key, value) == -1) {
+ goto error_cleanup;
+ }
}
if (PyDict_DelItem(class_dict, key) == -1) {
goto error_cleanup;
@@ -1097,9 +1115,16 @@
r = PySet_Add(class_methods, value);
} else {
- if (PyDict_SetItem(class_dict, key, value) < 0) {
- Py_CLEAR(value);
- goto error_cleanup;
+ if (PyObjCSelector_IsHidden(value)) {
+ if (PyDict_DelItem(class_dict, key) == -1) {
+ goto error_cleanup;
+ }
+ } else {
+
+ if (PyDict_SetItem(class_dict, key, value) < 0) {
+ Py_CLEAR(value);
+ goto error_cleanup;
+ }
}
r = PySet_Add(instance_methods, value);
@@ -1210,6 +1235,13 @@
for (i = 0; i < PySequence_Fast_GET_SIZE(class_methods); i++) {
value = PySequence_Fast_GET_ITEM(class_methods, i);
+ if (PyBytes_Check(value)) {
+ int r = PySet_Add(hiddenClassSelectors, value);
+ if (r == -1) {
+ goto error_cleanup;
+ }
+ }
+
if (!PyObjCSelector_Check(value)) {
continue;
}
@@ -1233,6 +1265,19 @@
/* Set sel_class */
sel->sel_class = new_class;
+
+ if (sel->sel_flags & PyObjCSelector_kHIDDEN) {
+ PyObject* v = PyBytes_InternFromString(
+ sel_getName(PyObjCSelector_GetSelector(value)));
+ if (v == NULL) {
+ goto error_cleanup;
+ }
+ int r = PySet_Add(hiddenClassSelectors, v);
+ Py_DECREF(v);
+ if (r == -1) {
+ goto error_cleanup;
+ }
+ }
}
}
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/module.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/module.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/module.m Tue Mar 23 16:08:37 2010
@@ -220,16 +220,6 @@
static char* kwlist[] = { "targetClass", "methodsArray", NULL };
PyObject* classObject = NULL;
PyObject* methodsArray = NULL;
- Class targetClass;
- Py_ssize_t methodCount;
- Py_ssize_t methodIndex;
- int r;
- struct PyObjC_method *methodsToAdd;
- size_t curMethodIndex;
- struct PyObjC_method *classMethodsToAdd;
- size_t curClassMethodIndex;
- PyObject* extraDict = NULL;
- PyObject* metaDict = NULL;
if (!PyArg_ParseTupleAndKeywords(args, keywds,
"OO:classAddMethods", kwlist,
@@ -246,156 +236,21 @@
methodsArray, "methodsArray must be a sequence");
if (methodsArray == NULL) return NULL;
- targetClass = PyObjCClass_GetClass(classObject);
- methodCount = PySequence_Fast_GET_SIZE(methodsArray);
+ int r = PyObjCClass_AddMethods(classObject,
+ PySequence_Fast_ITEMS(methodsArray),
+ PySequence_Fast_GET_SIZE(methodsArray));
+ Py_DECREF(methodsArray);
- if (methodCount == 0) {
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- extraDict = PyDict_New();
- if (extraDict == NULL) {
- return NULL;
- }
-
- metaDict = PyDict_New();
- if (metaDict == NULL) {
- Py_DECREF(extraDict);
- return NULL;
- }
-
- methodsToAdd = PyMem_Malloc(sizeof(*methodsToAdd) * methodCount);
- if (methodsToAdd == NULL) {
- Py_DECREF(extraDict);
- Py_DECREF(metaDict);
- PyErr_NoMemory();
- return NULL;
- }
-
- classMethodsToAdd = PyMem_Malloc(sizeof(*methodsToAdd) * methodCount);
- if (classMethodsToAdd == NULL) {
- Py_DECREF(extraDict);
- Py_DECREF(metaDict);
- PyMem_Free(methodsToAdd);
- PyErr_NoMemory();
+ if (r == -1) {
return NULL;
}
-
- curMethodIndex = 0;
- curClassMethodIndex = 0;
-
- for (methodIndex = 0; methodIndex < methodCount; methodIndex++) {
- PyObject* aMethod = PySequence_Fast_GET_ITEM(
- methodsArray, methodIndex);
- PyObject* name;
- struct PyObjC_method *objcMethod;
-
- if (PyObjCNativeSelector_Check(aMethod)) {
- PyErr_Format(PyExc_TypeError,
- "Cannot add a native selector to other "
- "classes");
- goto cleanup_and_return_error;
- }
-
- aMethod = PyObjCSelector_FromFunction(
- NULL,
- aMethod,
- classObject,
- NULL);
- if (aMethod == NULL) {
- PyErr_Format(PyExc_TypeError ,
- "All objects in methodArray must be of "
- "type <objc.selector>, <function>, "
- " <method> or <classmethod>");
- goto cleanup_and_return_error;
- }
-
- /* install in methods to add */
- if (PyObjCSelector_IsClassMethod(aMethod)) {
- objcMethod = classMethodsToAdd + curClassMethodIndex++;
- } else {
- objcMethod = methodsToAdd + curMethodIndex++;
- }
-
- objcMethod->name = PyObjCSelector_GetSelector(aMethod);
- objcMethod->type = strdup(
- PyObjCSelector_Signature(aMethod));
-
- PyObjC_RemoveInternalTypeCodes((char*)(objcMethod->type));
- if (objcMethod->type == NULL) {
- goto cleanup_and_return_error;
- }
- objcMethod->imp = PyObjCFFI_MakeIMPForPyObjCSelector(
- (PyObjCSelector*)aMethod);
-
- name = PyObject_GetAttrString(aMethod, "__name__");
-
-#if PY_MAJOR_VERSION == 3
- if (PyBytes_Check(name)) {
- PyObject* t = PyUnicode_Decode(
- PyBytes_AsString(name),
- PyBytes_Size(name),
- NULL, NULL);
- if (t == NULL) {
- Py_DECREF(name); name = NULL;
- Py_DECREF(aMethod); aMethod = NULL;
- goto cleanup_and_return_error;
- }
- Py_DECREF(name);
- name = t;
- }
-#endif
-
- if (!PyObjCClass_HiddenSelector(classObject, objcMethod->name)) {
- if (PyObjCSelector_IsClassMethod(aMethod)) {
- r = PyDict_SetItem(metaDict, name, aMethod);
- } else {
- r = PyDict_SetItem(extraDict, name, aMethod);
- }
- Py_DECREF(name); name = NULL;
- Py_DECREF(aMethod); aMethod = NULL;
- if (r == -1) {
- goto cleanup_and_return_error;
- }
- } else {
- Py_DECREF(name); name = NULL;
- Py_DECREF(aMethod); aMethod = NULL;
- }
- }
-
- /* add the methods */
- if (curMethodIndex != 0) {
- class_addMethodList(targetClass, methodsToAdd, curMethodIndex);
- }
- PyMem_Free(methodsToAdd);
- if (curClassMethodIndex != 0) {
- class_addMethodList(object_getClass(targetClass),
- classMethodsToAdd, curClassMethodIndex);
- }
- PyMem_Free(classMethodsToAdd);
-
- r = PyDict_Merge(((PyTypeObject*)classObject)->tp_dict, extraDict, 1);
- if (r == -1) goto cleanup_and_return_error;
-
- r = PyDict_Merge(Py_TYPE(classObject)->tp_dict, metaDict, 1);
- if (r == -1) goto cleanup_and_return_error;
-
- Py_DECREF(extraDict); extraDict = NULL;
- Py_DECREF(metaDict); metaDict = NULL;
Py_INCREF(Py_None);
return Py_None;
-
-cleanup_and_return_error:
- Py_XDECREF(metaDict);
- Py_XDECREF(extraDict);
- if (methodsToAdd) PyMem_Free(methodsToAdd);
- if (classMethodsToAdd) PyMem_Free(classMethodsToAdd);
- return NULL;
}
+
PyDoc_STRVAR(remove_autorelease_pool_doc,
"removeAutoreleasePool()\n"
"\n"
@@ -1648,6 +1503,139 @@
return curval;
}
+/*
+ * Helper function for decoding XML metadata:
+ *
+ * This fixes an issue with metadata files: metadata files use
+ * _C_BOOL to represent type 'BOOL', but that the string should
+ * be used to represent 'bool' which has a different size on
+ * PPC. Therefore swap usage of _C_BOOL and _C_NSBOOL in data
+ * from metadata files.
+ */
+static void typecode2typecode(char* buf)
+{
+ /* Skip pointer declarations and anotations */
+ for (;;) {
+ switch(*buf) {
+ case _C_PTR:
+ case _C_IN:
+ case _C_OUT:
+ case _C_INOUT:
+ case _C_ONEWAY:
+ case _C_CONST:
+ buf++;
+ break;
+ default:
+ goto exit;
+ }
+ }
+exit:
+
+ switch (*buf) {
+ case _C_BOOL:
+ *buf = _C_NSBOOL;
+ break;
+ case _C_NSBOOL:
+ *buf = _C_BOOL;
+ break;
+ case _C_STRUCT_B:
+ while (buf && *buf != _C_STRUCT_E && *buf && *buf++ != '=') {
+ }
+ while (buf && *buf && *buf != _C_STRUCT_E) {
+ if (*buf == '"') {
+ /* embedded field name */
+ buf = strchr(buf+1, '"');
+ if (buf == NULL) {
+ return;
+ }
+ buf++;
+ }
+ typecode2typecode(buf);
+ buf = (char*)PyObjCRT_SkipTypeSpec(buf);
+ }
+ break;
+
+ case _C_UNION_B:
+ while (buf && *buf != _C_UNION_E && *buf && *buf++ != '=') {
+ }
+ while (buf && *buf && *buf != _C_UNION_E) {
+ if (*buf == '"') {
+ /* embedded field name */
+ buf = strchr(buf+1, '"');
+ if (buf == NULL) {
+ return;
+ }
+ buf++;
+ }
+ typecode2typecode(buf);
+ buf = (char*)PyObjCRT_SkipTypeSpec(buf);
+ }
+ break;
+
+
+ case _C_ARY_B:
+ while (isdigit(*++buf));
+ typecode2typecode(buf);
+ break;
+ }
+}
+
+
+
+static PyObject*
+typestr2typestr(PyObject* args)
+{
+ char* s;
+ char* buf;
+
+ if (PyUnicode_Check(args)) {
+ PyObject* bytes = PyUnicode_AsEncodedString(args, NULL, NULL);
+ if (bytes == NULL) {
+ return NULL;
+ }
+ buf = PyObjCUtil_Strdup(PyBytes_AsString(args));
+ Py_DECREF(bytes);
+
+ } else if (PyBytes_Check(args)) {
+ buf = PyObjCUtil_Strdup(PyBytes_AsString(args));
+ } else {
+ PyErr_SetString(PyExc_TypeError, "expecing string");
+ return NULL;
+ }
+
+
+ if (buf == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ s = buf;
+ while (s && *s) {
+ typecode2typecode(s);
+ if (s && *s == '\"') {
+ PyErr_Format(PyObjCExc_InternalError,
+ "typecode2typecode: invalid typecode '%c' "
+ "at \"%s\"", *s, s);
+ *s = '\0';
+ PyMem_Free(buf);
+ return NULL;
+
+ } else {
+ s = (char*)PyObjCRT_SkipTypeSpec(s);
+ }
+ }
+
+ PyObject* result = PyString_FromString(buf);
+ PyMem_Free(buf);
+
+ return result;
+}
+
+
+
+
+
+
static PyMethodDef mod_methods[] = {
{
@@ -1757,6 +1745,9 @@
METH_VARARGS,
"_block_call(block, signature, args, kwds) -> retval" },
+ { "_typestr2typestr", (PyCFunction)typestr2typestr,
+ METH_O, "private function" },
+
{ 0, 0, 0, 0 } /* sentinel */
};
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.h Tue Mar 23 16:08:37 2010
@@ -95,6 +95,7 @@
int useKVO;
PyObject* protectedMethods;
PyObject* hiddenSelectors;
+ PyObject* hiddenClassSelectors;
struct _PyObjCClassObject* meta_class; /* To be dropped */
} PyObjCClassObject;
@@ -110,7 +111,9 @@
void PyObjCClass_SetDelMethod(PyObject* cls, PyObject* newval);
int PyObjCClass_HasPythonImplementation(PyObject* cls);
PyObject* PyObjCClass_ClassForMetaClass(PyObject* meta);
-BOOL PyObjCClass_HiddenSelector(PyObject* tp, SEL sel);
+BOOL PyObjCClass_HiddenSelector(PyObject* tp, SEL sel, BOOL classMethod);
+int PyObjCClass_SetHidden(PyObject* tp, SEL sel, BOOL classMethod);
+int PyObjCClass_AddMethods(PyObject* cls, PyObject** methods, Py_ssize_t count);
PyObject* PyObjCClass_ListProperties(PyObject* cls);
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.m Tue Mar 23 16:08:37 2010
@@ -7,8 +7,36 @@
#include <stddef.h>
+int PyObjCClass_SetHidden(PyObject* tp, SEL sel, BOOL classMethod)
+{
+ PyObject* hidden;
+ if (classMethod) {
+ hidden = ((PyObjCClassObject*)tp)->hiddenClassSelectors;
+ if (hidden == NULL) {
+ hidden = PySet_New(NULL);
+ if (hidden == NULL) {
+ return -1;
+ }
+ ((PyObjCClassObject*)tp)->hiddenClassSelectors = hidden;
+ }
+ } else {
+ hidden = ((PyObjCClassObject*)tp)->hiddenSelectors;
+ if (hidden == NULL) {
+ hidden = PySet_New(NULL);
+ if (hidden == NULL) {
+ return -1;
+ }
+ ((PyObjCClassObject*)tp)->hiddenSelectors = hidden;
+ }
+ }
+ PyObject* v = PyBytes_InternFromString(sel_getName(sel));
+ int r = PySet_Add(hidden, v);
+ Py_DECREF(v);
+ return r;
+}
+
-BOOL PyObjCClass_HiddenSelector(PyObject* tp, SEL sel)
+BOOL PyObjCClass_HiddenSelector(PyObject* tp, SEL sel, BOOL classMethod)
{
PyObject* mro = ((PyTypeObject*)tp)->tp_mro;
int i, n;
@@ -21,7 +49,12 @@
for (i = 0; i < n; i++) {
PyObject* base = PyTuple_GET_ITEM(mro, i);
if (PyObjCClass_Check(base)) {
- PyObject* hidden = ((PyObjCClassObject*)base)->hiddenSelectors;
+ PyObject* hidden;
+ if (classMethod) {
+ hidden = ((PyObjCClassObject*)base)->hiddenClassSelectors;
+ } else {
+ hidden = ((PyObjCClassObject*)base)->hiddenSelectors;
+ }
if (hidden != NULL) {
PyObject* v = PyBytes_InternFromString(sel_getName(sel));
if (v == NULL) {
@@ -109,7 +142,7 @@
nsdata_getsegcount,
NULL
#if PY_VERSION_HEX >= 0x02060000
- , NULL
+ , nsdata_getbuffer
, NULL
#endif
@@ -127,7 +160,7 @@
nsdata_getsegcount,
NULL
#if PY_VERSION_HEX >= 0x02060000
- , NULL
+ , nsmutabledata_getbuffer
, NULL
#endif
@@ -378,6 +411,7 @@
Ivar var;
PyObject* protectedMethods = NULL;
PyObject* hiddenSelectors = NULL;
+ PyObject* hiddenClassSelectors = NULL;
BOOL isCFProxyClass = NO;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "sOO:__new__",
@@ -432,6 +466,13 @@
return NULL;
}
+ hiddenClassSelectors = PySet_New(NULL);
+ if (hiddenClassSelectors == NULL) {
+ Py_DECREF(protectedMethods);
+ Py_DECREF(hiddenSelectors);
+ return NULL;
+ }
+
/*
* __pyobjc_protocols__ contains the list of protocols supported
@@ -445,6 +486,7 @@
if (protocols == NULL) {
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
} else {
@@ -456,6 +498,7 @@
if (seq == NULL) {
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
Py_DECREF(protocols);
return NULL;
}
@@ -466,6 +509,7 @@
if (protocols == NULL) {
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
for (i = 0; i < protocols_len; i++) {
@@ -481,12 +525,14 @@
Py_DECREF(protocols);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
PyList_Append(real_bases, py_super_class);
if (PyErr_Occurred()) {
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
Py_DECREF(protocols);
Py_DECREF(real_bases);
return NULL;
@@ -499,6 +545,7 @@
Py_DECREF(real_bases);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
if (PyObjCClass_Check(v)) {
@@ -506,6 +553,7 @@
Py_DECREF(real_bases);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
PyErr_SetString(PyExc_TypeError,
"multiple objective-C bases");
return NULL;
@@ -524,6 +572,7 @@
Py_DECREF(real_bases);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
@@ -534,13 +583,14 @@
/* First generate the objective-C class. This may change the
* class dict.
*/
- objc_class = PyObjCClass_BuildClass(super_class, protocols, name, dict, metadict, hiddenSelectors);
+ objc_class = PyObjCClass_BuildClass(super_class, protocols, name, dict, metadict, hiddenSelectors, hiddenClassSelectors);
if (objc_class == NULL) {
Py_DECREF(protocols);
Py_DECREF(metadict);
Py_DECREF(real_bases);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
@@ -554,6 +604,7 @@
Py_DECREF(metadict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
} else {
PyObjCClass_CheckMethodList(py_super_class, 1);
@@ -573,6 +624,7 @@
Py_DECREF(real_bases);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
Py_DECREF(real_bases);
@@ -598,6 +650,7 @@
Py_DECREF(metadict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
(void)PyObjCClass_UnbuildClass(objc_class);
return NULL;
}
@@ -609,6 +662,7 @@
Py_DECREF(metadict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
(void)PyObjCClass_UnbuildClass(objc_class);
return NULL;
}
@@ -625,6 +679,7 @@
Py_DECREF(metadict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
(void)PyObjCClass_UnbuildClass(objc_class);
return NULL;
}
@@ -653,6 +708,7 @@
Py_DECREF(metadict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
} else {
if (PyDict_DelItemString(dict, "__del__") < 0) {
@@ -664,6 +720,7 @@
Py_DECREF(metadict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
}
@@ -683,6 +740,7 @@
Py_DECREF(metadict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
@@ -695,6 +753,7 @@
Py_DECREF(metadict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
}
@@ -711,6 +770,7 @@
Py_DECREF(metadict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
if (PyDict_Update(metatype->tp_dict, metadict) == -1) {
@@ -720,6 +780,7 @@
Py_DECREF(metadict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
return NULL;
}
} else {
@@ -743,6 +804,7 @@
Py_DECREF(old_dict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
(void)PyObjCClass_UnbuildClass(objc_class);
return NULL;
}
@@ -766,6 +828,7 @@
Py_DECREF(old_dict);
Py_DECREF(protectedMethods);
Py_DECREF(hiddenSelectors);
+ Py_DECREF(hiddenClassSelectors);
(void)PyObjCClass_UnbuildClass(objc_class);
return NULL;
}
@@ -788,6 +851,7 @@
info->isCFWrapper = 0;
info->protectedMethods = protectedMethods;
info->hiddenSelectors = hiddenSelectors;
+ info->hiddenClassSelectors = hiddenClassSelectors;
var = class_getInstanceVariable(objc_class, "__dict__");
@@ -966,6 +1030,8 @@
return result;
}
+
+
/* Try to find the method anyway */
PyErr_Clear();
if (PyUnicode_Check(name)) {
@@ -973,7 +1039,7 @@
if (bytes == NULL) {
return NULL;
}
- if (PyObjCClass_HiddenSelector(self, sel_getUid(PyString_AsString(bytes)))) {
+ if (PyObjCClass_HiddenSelector(self, sel_getUid(PyString_AsString(bytes)), YES)) {
Py_DECREF(bytes);
PyErr_SetObject(PyExc_AttributeError, name);
return NULL;
@@ -982,7 +1048,7 @@
Py_DECREF(bytes);
#if PY_MAJOR_VERSION == 2
} else if (PyString_Check(name)) {
- if (PyObjCClass_HiddenSelector(self, sel_getUid(PyString_AsString(name)))) {
+ if (PyObjCClass_HiddenSelector(self, sel_getUid(PyString_AsString(name)), YES)) {
PyErr_SetObject(PyExc_AttributeError, name);
return NULL;
}
@@ -1116,7 +1182,8 @@
}
- if (PyObjCClass_HiddenSelector(self, PyObjCSelector_GetSelector(newVal))) {
+ if (PyObjCClass_HiddenSelector(self, PyObjCSelector_GetSelector(newVal),
+ PyObjCSelector_IsClassMethod(newVal))) {
Py_DECREF(newVal);
} else {
if (PyObjCSelector_IsClassMethod(newVal)) {
@@ -1482,7 +1549,7 @@
/* Check if the selector should be hidden */
if (PyObjCClass_HiddenSelector(py_class,
- method_getName(methods[i]))) {
+ method_getName(methods[i]), NO)) {
continue;
}
@@ -1536,7 +1603,7 @@
/* Check if the selector should be hidden */
if (PyObjCClass_HiddenSelector(py_class,
- method_getName(methods[i]))) {
+ method_getName(methods[i]), YES)) {
continue;
}
@@ -2268,3 +2335,168 @@
return PyObjCClass_New(objc_metaclass_locate(meta));
}
+
+int PyObjCClass_AddMethods(PyObject* classObject, PyObject** methods, Py_ssize_t methodCount)
+{
+ Class targetClass;
+ Py_ssize_t methodIndex;
+ int r;
+ struct PyObjC_method *methodsToAdd;
+ size_t curMethodIndex;
+ struct PyObjC_method *classMethodsToAdd;
+ size_t curClassMethodIndex;
+ PyObject* extraDict = NULL;
+ PyObject* metaDict = NULL;
+
+ targetClass = PyObjCClass_GetClass(classObject);
+ if (targetClass == NULL) {
+ return -1;
+ }
+
+ if (methodCount == 0) {
+ return 0;
+ }
+
+ extraDict = PyDict_New();
+ if (extraDict == NULL) {
+ return -1;
+ }
+
+ metaDict = PyDict_New();
+ if (metaDict == NULL) {
+ Py_DECREF(extraDict);
+ return -1;
+ }
+
+ methodsToAdd = PyMem_Malloc(sizeof(*methodsToAdd) * methodCount);
+ if (methodsToAdd == NULL) {
+ Py_DECREF(extraDict);
+ Py_DECREF(metaDict);
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ classMethodsToAdd = PyMem_Malloc(sizeof(*methodsToAdd) * methodCount);
+ if (classMethodsToAdd == NULL) {
+ Py_DECREF(extraDict);
+ Py_DECREF(metaDict);
+ PyMem_Free(methodsToAdd);
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ curMethodIndex = 0;
+ curClassMethodIndex = 0;
+
+ for (methodIndex = 0; methodIndex < methodCount; methodIndex++) {
+ PyObject* aMethod = methods[methodIndex];
+ PyObject* name;
+ struct PyObjC_method *objcMethod;
+
+ if (PyObjCNativeSelector_Check(aMethod)) {
+ PyErr_Format(PyExc_TypeError,
+ "Cannot add a native selector to other "
+ "classes");
+ goto cleanup_and_return_error;
+ }
+
+ aMethod = PyObjCSelector_FromFunction(
+ NULL,
+ aMethod,
+ classObject,
+ NULL);
+ if (aMethod == NULL) {
+ PyErr_Format(PyExc_TypeError ,
+ "All objects in methodArray must be of "
+ "type <objc.selector>, <function>, "
+ " <method> or <classmethod>");
+ goto cleanup_and_return_error;
+ }
+
+ /* install in methods to add */
+ if (PyObjCSelector_IsClassMethod(aMethod)) {
+ objcMethod = classMethodsToAdd + curClassMethodIndex++;
+ } else {
+ objcMethod = methodsToAdd + curMethodIndex++;
+ }
+
+ objcMethod->name = PyObjCSelector_GetSelector(aMethod);
+ objcMethod->type = strdup(
+ PyObjCSelector_Signature(aMethod));
+
+ PyObjC_RemoveInternalTypeCodes((char*)(objcMethod->type));
+ if (objcMethod->type == NULL) {
+ goto cleanup_and_return_error;
+ }
+ objcMethod->imp = PyObjCFFI_MakeIMPForPyObjCSelector(
+ (PyObjCSelector*)aMethod);
+
+ name = PyObject_GetAttrString(aMethod, "__name__");
+
+#if PY_MAJOR_VERSION == 3
+ if (PyBytes_Check(name)) {
+ PyObject* t = PyUnicode_Decode(
+ PyBytes_AsString(name),
+ PyBytes_Size(name),
+ NULL, NULL);
+ if (t == NULL) {
+ Py_DECREF(name); name = NULL;
+ Py_DECREF(aMethod); aMethod = NULL;
+ goto cleanup_and_return_error;
+ }
+ Py_DECREF(name);
+ name = t;
+ }
+#endif
+ if (PyObjCSelector_IsHidden(aMethod)) {
+ r = PyObjCClass_SetHidden(classObject, objcMethod->name, PyObjCSelector_IsClassMethod(aMethod));
+ if (r == -1) {
+ goto cleanup_and_return_error;
+ }
+ }
+
+ r = 0;
+ if (!PyObjCClass_HiddenSelector(classObject, objcMethod->name,
+ PyObjCSelector_IsClassMethod(aMethod))) {
+ if (PyObjCSelector_IsClassMethod(aMethod)) {
+ r = PyDict_SetItem(metaDict, name, aMethod);
+ } else {
+ r = PyDict_SetItem(extraDict, name, aMethod);
+ }
+ }
+ Py_DECREF(name); name = NULL;
+ Py_DECREF(aMethod); aMethod = NULL;
+ if (r == -1) {
+ goto cleanup_and_return_error;
+ }
+ }
+
+ /* add the methods */
+ if (curMethodIndex != 0) {
+ class_addMethodList(targetClass, methodsToAdd, curMethodIndex);
+ }
+ PyMem_Free(methodsToAdd);
+ if (curClassMethodIndex != 0) {
+ class_addMethodList(object_getClass(targetClass),
+ classMethodsToAdd, curClassMethodIndex);
+ }
+ PyMem_Free(classMethodsToAdd);
+
+ r = PyDict_Merge(((PyTypeObject*)classObject)->tp_dict, extraDict, 1);
+ if (r == -1) goto cleanup_and_return_error;
+
+ r = PyDict_Merge(Py_TYPE(classObject)->tp_dict, metaDict, 1);
+ if (r == -1) goto cleanup_and_return_error;
+
+ Py_DECREF(extraDict); extraDict = NULL;
+ Py_DECREF(metaDict); metaDict = NULL;
+
+ return 0;
+
+cleanup_and_return_error:
+ Py_XDECREF(metaDict);
+ Py_XDECREF(extraDict);
+ if (methodsToAdd) PyMem_Free(methodsToAdd);
+ if (classMethodsToAdd) PyMem_Free(classMethodsToAdd);
+ return -1;
+}
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/selector.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/selector.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/selector.h Tue Mar 23 16:08:37 2010
@@ -63,6 +63,7 @@
Class PyObjCSelector_GetClass(PyObject* obj);
int PyObjCSelector_Required(PyObject* obj);
int PyObjCSelector_IsClassMethod(PyObject* obj);
+int PyObjCSelector_IsHidden(PyObject* obj);
int ObjC_SignatureForSelector(char* class_name, SEL selector, char* signature);
PyObjCMethodSignature* PyObjCSelector_GetMetadata(PyObject* _self);
@@ -77,6 +78,7 @@
PyObject* PyObjCSelector_New(PyObject* callable, SEL selector, char* signature, int class_method, Class class) ;
SEL PyObjCSelector_DefaultSelector(const char* methname);
+
PyObject*
PyObjCSelector_FromFunction(
PyObject* pyname,
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/selector.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/selector.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/selector.m Tue Mar 23 16:08:37 2010
@@ -782,6 +782,20 @@
NSMethodSignature* methsig;
char buf[1024];
+ if (PyObjCObject_Check(self)) {
+ if (PyObjCClass_HiddenSelector((PyObject*)Py_TYPE(self), sel, NO)) {
+ PyErr_Format(PyExc_AttributeError,
+ "No attribute %s", name);
+ return NULL;
+ }
+ } else {
+ if (PyObjCClass_HiddenSelector(self, sel, YES)) {
+ PyErr_Format(PyExc_AttributeError,
+ "No attribute %s", name);
+ return NULL;
+ }
+ }
+
if (Object_class == nil) {
Object_class = [Object class];
}
@@ -1487,7 +1501,7 @@
{
static char* keywords[] = { "function", "selector", "signature",
"isClassMethod", "argumentTypes",
- "returnType", "isRequired", NULL };
+ "returnType", "isRequired", "isHidden", NULL };
PyObjCPythonSelector* result;
PyObject* callable;
char* signature = NULL;
@@ -1498,11 +1512,12 @@
int class_method = 0;
char signature_buf[1024];
int required = 1;
+ int hidden = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwds,
- "O|"Py_ARG_BYTES Py_ARG_BYTES"issi:selector",
+ "O|"Py_ARG_BYTES Py_ARG_BYTES"issii:selector",
keywords, &callable, &selector, &signature,
- &class_method, &argtypes, &rettype, &required)) {
+ &class_method, &argtypes, &rettype, &required, &hidden)) {
return NULL;
}
@@ -1585,6 +1600,9 @@
if (required) {
result->sel_flags |= PyObjCSelector_kREQUIRED;
}
+ if (hidden) {
+ result->sel_flags |= PyObjCSelector_kHIDDEN;
+ }
return (PyObject *)result;
}
@@ -1788,6 +1806,11 @@
return (PyObjCSelector_GetFlags(obj) & PyObjCSelector_kCLASS_METHOD) != 0;
}
+int PyObjCSelector_IsHidden(PyObject* obj)
+{
+ return (PyObjCSelector_GetFlags(obj) & PyObjCSelector_kHIDDEN) != 0;
+}
+
int PyObjCSelector_GetFlags(PyObject* obj)
{
return ((PyObjCSelector*)obj)->sel_flags;
@@ -1903,6 +1926,9 @@
if (result->callable) {
Py_INCREF(result->callable);
}
+ if (PyObjCClass_HiddenSelector(template_class, PyObjCSelector_GetSelector(callable), PyObjCSelector_IsClassMethod(callable))) {
+ ((PyObjCSelector*)result)->sel_flags |= PyObjCSelector_kHIDDEN;
+ }
return (PyObject*)result;
}
@@ -2001,6 +2027,9 @@
* is.
*/
super_sel = PyObjCClass_FindSelector(template_class, selector, is_class_method);
+ if (super_sel == NULL) {
+ PyErr_Clear();
+ }
if (is_class_method) {
meth = class_getClassMethod(oc_class, selector);
@@ -2028,17 +2057,22 @@
* the user may have specified a more exact
* signature!
*/
+ char* typestr = NULL;
+
if (super_sel == NULL) {
- return NULL;
+ /* FIXME: This isn't optimal when hiding methods with non-standard types */
+ typestr = method_getTypeEncoding(meth);
+ } else {
+ typestr = PyObjCSelector_Signature(super_sel);
}
value = PyObjCSelector_New(
callable,
selector,
- PyObjCSelector_Signature(super_sel),
+ typestr,
is_class_method,
oc_class);
- Py_DECREF(super_sel);
+ Py_XDECREF(super_sel);
} else {
char* signature = NULL;
@@ -2058,7 +2092,7 @@
is_class_method,
oc_class);
}
- if (PyObjCClass_HiddenSelector(template_class, selector)) {
+ if (PyObjCClass_HiddenSelector(template_class, selector, PyObjCSelector_IsClassMethod(value))) {
((PyObjCSelector*)value)->sel_flags |= PyObjCSelector_kHIDDEN;
}
Modified: trunk/pyobjc/pyobjc-core/NEWS.txt
==============================================================================
--- trunk/pyobjc/pyobjc-core/NEWS.txt (original)
+++ trunk/pyobjc/pyobjc-core/NEWS.txt Tue Mar 23 16:08:37 2010
@@ -140,7 +140,7 @@
(At the very least least: the PyObjCMethodSignature objects can be shared
more than they are now).
- This needs further investigation to determine why we use more memory
+ This needs further investigation to determine why we seem to use more memory
than Ruby.
- TODO: Drop support for 2.5 and
Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_hidden_selector.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_hidden_selector.py (original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_hidden_selector.py Tue Mar 23 16:08:37 2010
@@ -1,43 +1,202 @@
from PyObjCTools.TestSupport import *
import objc
+class hidden_method (object):
+ def __pyobjc_class_setup__(self, name, class_dict, instance_methods, class_methods):
+ @objc.selector
+ def method(self):
+ return 42
+
+ method.isHidden = True
+
+ def clsmethod(self):
+ return 99
+ clsmethod=objc.selector(clsmethod, isClassMethod=True)
+ clsmethod.isHidden = True
+
+ instance_methods.add(method)
+ class_methods.add(clsmethod)
+
+
+
+class OCTestHidden (objc.lookUpClass('NSObject')):
+ m = hidden_method()
+
+ @objc.selector
+ def body(self):
+ return "BODY"
+ body.isHidden = True
+
+
+ def bodyclass(self):
+ return "BODYCLASS"
+ bodyclass=objc.selector(bodyclass, isClassMethod=True)
+ bodyclass.isHidden=True
+
+ @objc.selector
+ def somebody(self):
+ return "instance"
+ somebody.isHidden = True
+
+ def boolMethod(self):
+ return 1
+ boolMethod = objc.selector(boolMethod, signature=objc._C_NSBOOL + '@:')
+ boolMethod.isHidden = True
+
+class OCTestSubHidden (OCTestHidden):
+ def body(self):
+ return "BODY2"
+
+ @classmethod
+ def bodyclass(self):
+ return "BODYCLASS2"
+
+ @classmethod
+ def somebody(self):
+ return "class"
+
+ def boolMethod(self):
+ return 0
class TestHiddenSelector (TestCase):
def testHiddenInClassDef(self):
- self.fail("todo")
+ o = OCTestHidden.alloc().init()
+ self.assertRaises(AttributeError, getattr, o, 'body')
- # define method in a class definition
- # and make the method read only (while
- # still in the class body). Check that
- # the method is not present in the class
- # __dict__, but is callable.
- #
- # (Callable means through pyobjc_instanceMethods,
- # not directly)
+ v = o.performSelector_(b'body')
+ self.assertEquals(v, "BODY")
- def testHiddenAddMethods(self):
- self.fail("todo")
+ v = o.pyobjc_instanceMethods.body()
+ self.assertEquals(v, "BODY")
+
+ self.assertRaises(AttributeError, getattr, OCTestHidden, 'bodyclass')
+ v = OCTestHidden.performSelector_(b'bodyclass')
+ self.assertEquals(v, "BODYCLASS")
+
+ v = OCTestHidden.pyobjc_classMethods.bodyclass()
+ self.assertEquals(v, "BODYCLASS")
+
+ o = OCTestHidden.alloc().init()
+ self.assertRaises(AttributeError, getattr, o, 'boolMethod')
+ v = o.pyobjc_instanceMethods.boolMethod()
+ self.assertIsObject(v, True)
- # Add a hidden selector using objc.classAddMethods
- # and check that the selector is callable but not
- # present in the class __dict__
- #
- # (Callable means through pyobjc_instanceMethods,
- # not directly)
def testHiddenInSetupHook(self):
- self.fail("todo")
+ o = OCTestHidden.alloc().init()
+
+ # Instance method
+ self.assertRaises(AttributeError, getattr, o, 'method')
+
+ v = o.performSelector_(b'method')
+ self.assertEquals(v, 42)
+
+ v = o.pyobjc_instanceMethods.method()
+ self.assertEquals(v, 42)
+
+ # Class method
+ self.assertRaises(AttributeError, getattr, OCTestHidden, 'clsmethod')
+
+ v = OCTestHidden.performSelector_(b'clsmethod')
+ self.assertEquals(v, 99)
+
+ v = OCTestHidden.pyobjc_classMethods.clsmethod()
+ self.assertEquals(v, 99)
+
+
+ def testHiddenAddMethods(self):
+
+ @objc.selector
+ def addedmethod(self):
+ return "NEW"
+ addedmethod.isHidden = True
+
+ def addedclass(self):
+ return "NEWCLASS"
+ addedclass=objc.selector(addedclass, isClassMethod=True)
+ addedclass.isHidden=True
+
+ objc.classAddMethods(OCTestHidden, [addedmethod, addedclass])
+
+ o = OCTestHidden.alloc().init()
+
+ # Instance method
+ self.assertRaises(AttributeError, getattr, o, 'addedmethod')
+
+ v = o.performSelector_(b'addedmethod')
+ self.assertEquals(v, "NEW")
+
+ v = o.pyobjc_instanceMethods.addedmethod()
+ self.assertEquals(v, "NEW")
+
+ # Class method
+ self.assertRaises(AttributeError, getattr, OCTestHidden, 'addedclass')
+
+ v = OCTestHidden.performSelector_(b'addedclass')
+ self.assertEquals(v, "NEWCLASS")
+
+ v = OCTestHidden.pyobjc_classMethods.addedclass()
+ self.assertEquals(v, "NEWCLASS")
+
+ def testClassVsInstance(self):
+ o = OCTestHidden.alloc().init()
+ self.assertRaises(AttributeError, getattr, o, "sombody")
+ v = o.performSelector_(b'somebody')
+ self.assertEquals(v, "instance")
+
+ v = OCTestSubHidden.somebody()
+ self.assertEquals(v, "class")
+
+ def testHiddenInSubClass(self):
+
+ # Instance
+ o = OCTestSubHidden.alloc().init()
+ self.assertRaises(AttributeError, getattr, o, "body")
+ v = o.performSelector_(b'body')
+ self.assertEquals(v, "BODY2")
+
+ @objc.selector
+ def subclassbody(self):
+ return "base"
+ subclassbody.isHidden = True
+
+ @objc.selector
+ def subclassbody2(self):
+ return "base2"
+ subclassbody.isHidden = True
+
+ objc.classAddMethods(OCTestHidden, [subclassbody, subclassbody2])
+
+
+ @objc.selector
+ def subclassbody(self):
+ return "sub"
+
+ @objc.selector
+ def subclassbody2(self):
+ return "sub2"
+
+ objc.classAddMethods(OCTestSubHidden, [subclassbody])
+ self.assertRaises(AttributeError, getattr, o, "subclassbody")
+ v = o.performSelector_(b'subclassbody')
+ self.assertEquals(v, "sub")
+
+ OCTestSubHidden.subclassbody2 = subclassbody2
+ #self.assertRaises(AttributeError, getattr, o, "subclassbody2")
+ v = o.performSelector_(b'subclassbody2')
+ self.assertEquals(v, "sub2")
- # Use a helper class with a __pyobjc_class_setup__
- # hook to insert hidden selectors in the class
- # dict and/or the instance and class methods lists,
- # check that this behaves correctly.
+ self.assertRaises(AttributeError, getattr, o, 'boolMethod')
+ v = o.pyobjc_instanceMethods.boolMethod()
+ self.assertIsObject(v, False)
- def testHiddenClassMethods(self):
- self.fail("todo")
+ # Class
+ self.assertRaises(AttributeError, getattr, OCTestSubHidden, 'bodyclass')
+ v = OCTestSubHidden.performSelector_(b'bodyclass')
+ self.assertEquals(v, "BODYCLASS2")
- # Same as testHiddenAddMethods, testHiddenInSetupHook
- # and testHiddenInClassDef, but now using a class method.
+ def testTypes(self):
+ self.fail("Add tests with objc._C_CHAR_AS_INT, objc._C_UNICHAR and complex APIs")
if __name__ == "__main__":
main()
Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_methodedits.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_methodedits.py (original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_methodedits.py Tue Mar 23 16:08:37 2010
@@ -212,14 +212,14 @@
MEClass.classSomethingElse = classmethod(lambda self: 2*2)
MEClass.classDuplicate_ = classmethod(lambda self, x: 2*x)
- self.assertTrue(MEClass.pyobjc_classMethods.respondsToSelector_("classSomethingElse"))
- self.assertTrue(MEClass.pyobjc_classMethods.respondsToSelector_("classDuplicate:"))
+ self.assertTrue(MEClass.pyobjc_classMethods.respondsToSelector_(b"classSomethingElse"))
+ self.assertTrue(MEClass.pyobjc_classMethods.respondsToSelector_(b"classDuplicate:"))
self.assertEquals(4, MEClass.classSomethingElse())
self.assertEquals(8, MEClass.classDuplicate_(4))
def testAssignFuzzyMethod(self):
- self.assertRaises(ValueError, setattr, MEClass, 'fuzzyMethod', objc.selector(None, selector=b'fuzzy', signature=b'@@:'))
+ self.assertRaises((ValueError, TypeError), setattr, MEClass, 'fuzzyMethod', objc.selector(None, selector=b'fuzzy', signature=b'@@:'))
def testRemovingMethods(self):
theClass = NSObject
Modified: trunk/pyobjc/pyobjc-core/setup.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/setup.py (original)
+++ trunk/pyobjc/pyobjc-core/setup.py Tue Mar 23 16:08:37 2010
@@ -1,6 +1,14 @@
#!/usr/bin/env python
import sys
+# We need at least Python 2.5
+MIN_PYTHON = (2, 5)
+
+if sys.version_info < MIN_PYTHON:
+ vstr = '.'.join(map(str, MIN_PYTHON))
+ raise SystemExit('PyObjC: Need at least Python ' + vstr)
+
+
if sys.version_info[:2] < (3, 0):
import ez_setup
ez_setup.use_setuptools()
@@ -94,12 +102,6 @@
# See the news file:
#os.environ['MACOSX_DEPLOYMENT_TARGET']='10.5'
-# We need at least Python 2.5
-MIN_PYTHON = (2, 5)
-
-if sys.version_info < MIN_PYTHON:
- vstr = '.'.join(map(str, MIN_PYTHON))
- raise SystemExit('PyObjC: Need at least Python ' + vstr)
# Set USE_SYSTEM_FFI to True to link to the system version
# of libffi
------------------------------------------------------------------------------
Download Intel® Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev