Commits

Ronald Oussoren committed 01d27e6

Futher py3k support:

* Test for Py3k Using PY_MAJOR_VERSION instead of PY_VERSION_HEX
* Add improved slice support structs (the older variation
doesn't work in py3k)
* Initial version of py3k style dict views.

  • Participants
  • Parent commits 6ba1eb3
  • Branches pyobjc-ancient

Comments (0)

Files changed (36)

pyobjc-core/Lib/objc/_convenience.py

 CLASS_METHODS['NSBlock'] = (
     ('__call__', __call__),
 )
+
+
+if sys.version_info[0] == 3 or (sys.version_info[0] == 2 and sys.version_info[1] >= 7):
+    class nsdict_view (object):
+        __slots__ = ()
+
+        def __and__(self, other):
+            result = set(self)
+            result.intersection_update(other)
+            return result
+
+        def __or__(self, other):
+            result = set(self)
+            result.update(other)
+            return result
+
+        def __sub__(self, other):
+            result = set(self)
+            result.difference_update(other)
+            return result
+
+        def __xor__(Self, other):
+            result = set(self)
+            result.symmetric_difference_update(other)
+            return result
+
+        def __len__(self):
+            return len(self.__value)
+
+    class nsdict_keys(nsdict_view):
+        __slots__=('__value')
+        def __init__(self, value):
+            self.__value =  value
+
+        def __iter__(self):
+            return iter(self.__value)
+
+        def __contains__(self, value):
+            return value in self.__value
+
+    class nsdict_values(nsdict_view):
+        __slots__=('__value')
+        def __init__(self, value):
+            self.__value =  value
+
+        def __iter__(self):
+            return iter(self.objectEnumerator())
+
+        def __contains__(self, value):
+            for v in iter(self):
+                if value == v:
+                    return True
+            return False
+
+    class nsdict_items(nsdict_view):
+        __slots__=('__value')
+        def __init__(self, value):
+            self.__value =  value
+
+        def __iter__(self):
+            for k in self.__value:
+                yield (k, self.__value[k])
+
+        def __contains__(self, value):
+            for v in iter(self):
+                if value == v:
+                    return True
+            return False
+
+    if sys.version_info[0] == 3:
+        CLASS_METHODS['NSDictionary'] = (
+            ('keys', lambda self: nsdict_keys(self)),
+            ('values', lambda self: nsdict_values(self)),
+            ('items', lambda self: nsdict_items(self)),
+        )
+
+    else:
+        CLASS_METHODS['NSDictionary'] = (
+            ('viewkeys', lambda self: nsdict_keys(self)),
+            ('viewvalues', lambda self: nsdict_values(self)),
+            ('viewitems', lambda self: nsdict_items(self)),
+        )
+

pyobjc-core/Lib/objc/_dyld.py

 
 def ensure_unicode(s):
     """Not all of PyObjC understands unicode paths very well yet"""
-    if isinstance(s, str):
+    if isinstance(s, bytes):
         return unicode(s, 'utf8')
     return s
 

pyobjc-core/Modules/objc/OC_PythonNumber.m

 			PyObjC_GIL_RETURN(@encode(BOOL));
 		} else if (PyFloat_Check(value)) {
 			PyObjC_GIL_RETURN(@encode(double));
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		} else if (PyInt_Check(value)) {
 			PyObjC_GIL_RETURN(@encode(long));
 #endif
 	BOOL negative = NO;
 
 	PyObjC_BEGIN_WITH_GIL
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		if (PyInt_Check(value)) {
 			long lng = PyInt_AsLong(value);
 			if (lng < 0) {
 	long long result;
 
 	PyObjC_BEGIN_WITH_GIL
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		if (PyInt_Check(value)) {
 			result =  PyInt_AsLong(value);
 			PyObjC_GIL_RETURN(result);
 		if (PyLong_Check(value)) {
 			result =  PyLong_AsUnsignedLongLongMask(value);
 			PyObjC_GIL_RETURN(result);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		} else if (PyInt_Check(value)) {
 			result =  (unsigned long long)PyInt_AsLong(value);
 			PyObjC_GIL_RETURN(result);
 			PyObjC_GIL_FORWARD_EXC();
 		}
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		PyObject* uniVal = PyUnicode_FromEncodedObject(repr, "ascii", "strict");
 		Py_DECREF(repr);
 		if (PyErr_Occurred()) {

pyobjc-core/Modules/objc/OC_PythonObject.m

 		PyObjC_RegisterObjCProxy(argument, rval);
 		r = 0;
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyInt_Check (argument)) {
 		rval = [OC_PythonNumber numberWithPythonObject:argument]; 
 		PyObjC_RegisterObjCProxy(argument, rval);
 			dictionaryWithPythonObject:argument];
 		PyObjC_RegisterObjCProxy(argument, rval);
 		r = 0;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(argument)) {
 		r = 0;
 		if (PyObjC_StrBridgeEnabled == 0) {
 
 		repr = PyObject_Repr (pyObject);
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		if (repr) {
 			int err;
 			NSString* result;

pyobjc-core/Modules/objc/OC_PythonString.m

 #include "pyobjc.h"
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 #import "OC_PythonString.h"
 
 @implementation OC_PythonString 

pyobjc-core/Modules/objc/block_support.m

 	return NULL;
 }
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 static void PyObjCBlock_CleanupCapsule(void* ptr)
 {
 	PyObjCFFI_FreeBlockFunction(ptr);

pyobjc-core/Modules/objc/bundle-variables.m

 
 		if (!PyArg_ParseTuple(item, 
 				"O!"Py_ARG_BYTES":variableInfo", 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 				&PyBaseString_Type,
 #else
 				&PyUnicode_Type,
 
 		doc = NULL;
 		if (!PyArg_ParseTuple(item, 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 				"O&s|SO;functionInfo", 
 #else
 				"O&y|UO;functionInfo", 
 
 		doc = NULL;
 		if (!PyArg_ParseTuple(item, 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 					"O!s|SO:functionInfo tuple", &PyBaseString_Type, 
 
 #else

pyobjc-core/Modules/objc/class-builder.m

 				PyBytes_AsString(bytes));
 			Py_DECREF(bytes);
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		}  else if (PyString_Check(slot_value)) {
 			var = (PyObjCInstanceVariable*)PyObjCInstanceVariable_New(
 				PyString_AS_STRING(slot_value));
 					PyErr_SetString(PyExc_ValueError, "empty name");
 					goto error_cleanup;
 				}
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			} else if (PyString_Check(pyname)) {
 				ocname = PyString_AS_STRING(pyname);
 #endif

pyobjc-core/Modules/objc/formal-protocol.m

 		aSelector = sel_getUid(s);
 		Py_DECREF(bytes);
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(sel)) {
 		char* s = PyString_AsString(sel);
 		if (*s == '\0') {
 		aSelector = sel_getUid(s);
 		Py_DECREF(bytes);
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(sel)) {
 		char* s = PyString_AsString(sel);
 		if (*s == '\0') {

pyobjc-core/Modules/objc/fsref.m

 	rc = FSRefMakePath( &((PyObjC_FSRefObject*)ref)->ref,
 			buffer, sizeof(buffer));
 	if (rc != 0) {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		PyMac_Error(rc);
 #else
 		PyErr_Format(PyExc_OSError, "MAC Error %d", rc);
 
 	if (PyUnicode_Check(path)) {
 		value = PyUnicode_AsEncodedString(path, NULL, NULL);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if(PyString_Check(path)) {
 		value = path; Py_INCREF(path);
 #endif
 	rc = FSPathMakeRef((UInt8*)PyBytes_AsString(value), &result, &isDirectory);
 	Py_DECREF(value);
 	if (rc != 0) {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		PyMac_Error(rc);
 #else
 		PyErr_Format(PyExc_OSError, "MAC Error %d", rc);

pyobjc-core/Modules/objc/function.m

 
 	if (self->name == NULL) {
 		return PyText_FromFormat("<objc.function object at %p>", self);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(self->name)) {
 		return PyString_FromFormat("<objc.function '%s' at %p>", PyString_AsString(self->name), self);
 #else
 		return PyUnicode_FromFormat("<objc.function %R at %p>", self->name, self);
 #endif
 	} else {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		PyObject* result;
 		PyObject* name_repr = PyObject_Repr(self->name);
 		if (name_repr == NULL) {

pyobjc-core/Modules/objc/informal-protocol.m

 
 	if (PyUnicode_Check(self->name)) {
 		b = PyUnicode_AsEncodedString(self->name, NULL, NULL);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(self->name)) {
 		b = self->name; Py_INCREF(b);
 #endif
 
 	if (PyUnicode_Check(name)) {
 		/* pass */
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(name)) {
 		/* pass */
 #endif

pyobjc-core/Modules/objc/instance-var.m

 			return -1;
 		}
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(name)) {
 		self->name = PyObjCUtil_Strdup(PyString_AS_STRING(name));
 #endif

pyobjc-core/Modules/objc/libffi_support.m

 
 static ffi_type* signature_to_ffi_type(const char* argtype);
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 static void cleanup_ffitype_capsule(void* ptr, void* context __attribute__((__unused__)))
 
 {
 			byref[curarg] = PyMem_Malloc(sizeof(int));
 			arglist[curarg] = signature_to_ffi_type(@encode(int));
 			v = PyTuple_GET_ITEM(argtuple, argoffset);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			if (PyString_Check(v)) {
 				if (PyString_Size(v) != 1) {
 					PyErr_SetString(PyExc_ValueError, "Expecting string of length 1");
 }
 
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 static void imp_capsule_cleanup(void* ptr, void* context __attribute__((__unused__)))
 {
 	PyObjCFFI_FreeIMP(ptr);

pyobjc-core/Modules/objc/method-accessor.m

 		if (name_bytes == NULL) {
 			return NULL;
 		}
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(name)) {
 		name_bytes = name; Py_INCREF(name_bytes);
 #endif 
 {
 	ObjCMethodAccessor* self = (ObjCMethodAccessor*)_self;
 	PyObject* rval;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	PyObject* repr;
 
 	repr = PyObject_Repr(self->base);

pyobjc-core/Modules/objc/method-signature.m

 					return -1;
 				}
 			} 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			else if (PyString_Check(d)) {
 				descr->sel_type = PyObjCUtil_Strdup(PyString_AsString(d));
 				if (descr->sel_type == NULL) {
 					return -1;
 				}
 			}
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			else if (PyInt_Check(d)) {
 				descr->ptrType = PyObjC_kFixedLengthArray;
 				descr->arrayArg = PyInt_AsLong(d);
 				}
 				descr->arrayArgOut = descr->arrayArg;
 					
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			} else if (PyInt_Check(d)) {
 				descr->ptrType = PyObjC_kArrayCountInArg;
 				descr->arrayArg = PyInt_AsLong(d);
 					if (PyLong_Check(PyTuple_GET_ITEM(d, 0))) {
 						descr->arrayArg = PyLong_AsLong(PyTuple_GET_ITEM(d, 0));
 					} else {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 						descr->arrayArg = PyInt_AsLong(PyTuple_GET_ITEM(d, 0));
 #else
 						PyErr_SetString(PyExc_TypeError, "array_out argument not integer");
 					if (PyLong_Check(PyTuple_GET_ITEM(d, 0))) {
 						descr->arrayArg = PyLong_AsLong(PyTuple_GET_ITEM(d, 0));
 					} else {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 						descr->arrayArg = PyInt_AsLong(PyTuple_GET_ITEM(d, 0));
 #else
 						PyErr_SetString(PyExc_TypeError, "array_out argument not integer");
 					if (PyLong_Check(PyTuple_GET_ITEM(d, 1))) {
 						descr->arrayArgOut = PyLong_AsLong(PyTuple_GET_ITEM(d, 1));
 					} else {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 						descr->arrayArgOut = PyInt_AsLong(PyTuple_GET_ITEM(d, 1));
 #else
 						PyErr_SetString(PyExc_TypeError, "array_out argument not integer");
 				}
 				typeModifier = *PyBytes_AsString(bytes);
 				Py_DECREF(bytes);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			} else if (PyString_Check(d)) {
 				typeModifier = *PyString_AsString(d);
 #else
 
 	if (d 
 		&& (
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		  PyString_Check(d) ||
 #else
 		  PyBytes_Check(d) ||
 			if (bytes == NULL) {
 				return -1;
 			}
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		} else if (PyString_Check(d)) {
 			bytes = d; Py_INCREF(bytes);
 #else
 				return NULL;
 			}
 		}
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		else if (PyInt_Check(v)) {
 			methinfo->arrayArg = PyInt_AsLong(v);
 		}

pyobjc-core/Modules/objc/module.m

 
 PyObject* PyObjCClass_DefaultModule = NULL;
 PyObject* PyObjC_NSNumberWrapper = NULL;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 PyObject* PyObjCStrBridgeWarning = NULL;
 int PyObjC_StrBridgeEnabled = 1;
 #endif
 	return rval;
 }
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 PyDoc_STRVAR(setStrBridgeEnabled_doc,
   "setStrBridgeEnabled(bool)\n"
   "\n"
 		
 		name = PyObject_GetAttrString(aMethod, "__name__");
 
-#if PY_VERSION_HEX >= 0x03000000
+#if PY_MAJOR_VERSION == 2
 		if (PyBytes_Check(name)) {
 			PyObject* t = PyUnicode_Decode(
 					PyBytes_AsString(name),
 		return NULL;
 	}
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	return PyBuffer_New(length);
 #else
 	return PyByteArray_FromStringAndSize(NULL, length);
 	PyObject* scanClasses = NULL;
 
 	if (!PyArg_ParseTupleAndKeywords(args, kwds, 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			"SO|O&O&O",
 #else
 			"UO|O&O&O",
 				}
 				fieldnames[i] = PyObjCUtil_Strdup(PyBytes_AsString(bytes));
 				Py_DECREF(bytes);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			} else if (PyString_Check(v)) {
 				fieldnames[i] = PyObjCUtil_Strdup(PyString_AS_STRING(v));
 #endif
   "Returns a closure object that can be used to call the function from\n"
   "C. This object has no useable interface from Python.\n"
  );
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 static void _callback_cleanup(void* closure)
 {
 	PyObjCFFI_FreeIMP((IMP)closure);
 	{ "getVerbose", (PyCFunction)getVerbose, METH_VARARGS|METH_KEYWORDS, getVerbose_doc },
 	{ "pyobjc_id", (PyCFunction)pyobjc_id, METH_VARARGS|METH_KEYWORDS, pyobjc_id_doc },
 	{ "repythonify", (PyCFunction)repythonify, METH_VARARGS|METH_KEYWORDS, repythonify_doc },
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	{ "setStrBridgeEnabled", (PyCFunction)setStrBridgeEnabled, METH_VARARGS|METH_KEYWORDS, setStrBridgeEnabled_doc },
 	{ "getStrBridgeEnabled", (PyCFunction)getStrBridgeEnabled, METH_VARARGS|METH_KEYWORDS, getStrBridgeEnabled_doc },
 #endif
 };
 
 
-#if PY_VERSION_HEX >= 0x03000000
+#if PY_MAJOR_VERSION == 3
 static int mod_traverse(PyObject *m __attribute__((__unused__)), visitproc visit __attribute__((__unused__)), void *arg __attribute__((__unused__))) 
 {
 	/* FIXME: should traverse all globals */
 		INITERROR();
 	}
 
-#if PY_VERSION_HEX >= 0x03000000
+#if PY_MAJOR_VERSION == 3
 	m = PyModule_Create(&mod_module);
 #else
 	m = Py_InitModule4("_objc", mod_methods, NULL,
 		INITERROR();
 	}
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	PyObjCStrBridgeWarning = PyErr_NewException("objc.PyObjCStrBridgeWarning", PyExc_DeprecationWarning, NULL);
 	PyModule_AddObject(m, "PyObjCStrBridgeWarning", PyObjCStrBridgeWarning);
 #endif
 	global_release_pool = [[NSAutoreleasePool alloc] init];
 	[OC_NSAutoreleasePoolCollector newAutoreleasePool];
 
-#if PY_VERSION_HEX >= 0x03000000
+#if PY_MAJOR_VERSION == 3
 	return m;
 #endif
 

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

  *
  */
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 static
 Py_ssize_t nsdata_getreadbuffer(PyObject *pyself, Py_ssize_t segment __attribute__((unused)), void **ptrptr) {
 	NSData *self = (NSData *)PyObjCObject_GetObject(pyself);
 
 
 static PyBufferProcs nsdata_as_buffer = {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	nsdata_getreadbuffer,
 	NULL,
 	nsdata_getsegcount,
 };
 
 static PyBufferProcs nsmutabledata_as_buffer = {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	nsdata_getreadbuffer,
 	nsmutabledata_getwritebuffer,
 	nsdata_getsegcount,
 		PyErr_Clear();
 	}
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	else if (PyString_Check(name) 
 			&& strncmp(PyString_AS_STRING(name), "__", 2) == 0 
 			&& strcmp(PyString_AS_STRING(name), "__dict__") != 0) {
 		}
 		result = PyObjCSelector_FindNative(self, PyBytes_AsString(bytes));
 		Py_DECREF(bytes);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(name)) {
 		result = PyObjCSelector_FindNative(self, PyString_AsString(name));
 #endif
 	return result;
 }
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 static int
 class_compare(PyObject* self, PyObject* other)
 {
 				
 				continue;
 			}
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 
 		} else if (PyString_Check(k)) {
 			char* n = PyString_AS_STRING(k);

pyobjc-core/Modules/objc/objc-object.m

 		 * Don't call 'description' for uninitialized objects, that
 		 * is undefined behaviour and will crash the interpreter sometimes.
 		 */
-		res = PyObject_CallMethod((PyObject*)self, "description", NULL);
+		//res = PyObject_CallMethod((PyObject*)self, "description", NULL);
+		res = NULL;
 		if (res == NULL) {
 			PyErr_Clear();
 		} else {
 			dict = ((PyTypeObject *)base)->tp_dict;
 
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		} else if (PyClass_Check(base)) {
 			dict = ((PyClassObject*)base)->cl_dict;
 			protDict = NULL;
 	if (PyUnicode_Check(name)) {
 		bytes = PyUnicode_AsEncodedString(name, NULL, NULL);
 		if (bytes == NULL) return NULL;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(name)) {
 		bytes = name; Py_INCREF(bytes);
 #endif
 
 	obj_inst = PyObjCObject_GetObject(obj);
 	if (!obj_inst) {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		PyErr_Format(PyExc_AttributeError,
 		     "cannot access attribute '%.400s' of NIL '%.50s' object",
 		     PyString_AS_STRING(name),
 
 	f = NULL;
 	if (descr != NULL 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		&& PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS)
 #endif
 	    ) {
 		if (PyObjCSelector_Check(res) 
 				&& PyObjCSelector_IsClassMethod(res)) {
 			Py_DECREF(res);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			PyErr_Format(PyExc_AttributeError,
 			     "'%.50s' object has no attribute '%.400s'",
 			     tp->tp_name, PyString_AS_STRING(name));
 	if (PyUnicode_Check(name)) {
 		bytes = PyUnicode_AsEncodedString(name, NULL, NULL);
 		if (bytes == NULL) return -1;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(name)) {
 		bytes = name; Py_INCREF(bytes);
 #endif
 	descr = _type_lookup(tp, name);
 	f = NULL;
 	if (descr != NULL 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		&& PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS)
 #endif
 	   ) {
 #endif
 
      },
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
 #if PY_VERSION_HEX >= 0x02050000

pyobjc-core/Modules/objc/objc_super.m

 		   (i.e. super, or a subclass), not the class of su->obj. */
 		if (PyUnicode_Check(name)) {
 			skip = (PyUnicode_GET_SIZE(name) && PyObjC_is_ascii_string(name, "__class__"));
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		} else if (PyString_Check(name)) {
 			skip = (
 				PyString_GET_SIZE(name) == 9 &&
 				
 			} else if (PyType_Check(tmp))
 				dict = ((PyTypeObject *)tmp)->tp_dict;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			else if (PyClass_Check(tmp))
 				dict = ((PyClassObject *)tmp)->cl_dict;
 #endif

pyobjc-core/Modules/objc/objc_support.m

 #endif
 
 	case _C_ULNG:
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		if (*(unsigned long*)datum > LONG_MAX) {
 			retobject = (PyObject*)PyLong_FromUnsignedLongLong(
 				*(unsigned long*)datum);
 	PyObjC_Assert(descr != NULL, -1);
 	PyObjC_Assert(out != NULL, -1);
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	if (PyInt_Check (argument)) {
 		long temp = PyInt_AsLong(argument);
 		if (PyErr_Occurred()) {
 		PyObject* tmp;
 
 		if (
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			PyString_Check(argument) || 
 #else
 			PyBytes_Check(argument) || 
 	PyObjC_Assert(descr != NULL, -1);
 	PyObjC_Assert(out != NULL, -1);
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	if (PyInt_Check (argument)) {
 		*out = (long long)PyInt_AsLong(argument);
 		if (PyErr_Occurred()) {
 		PyObject* tmp;
 
 		if (
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			PyString_Check(argument) || 
 #else
 			PyBytes_Check(argument) || 
 			*(int*)datum = (int)(*PyUnicode_AsUnicode(argument));
 			return 0;
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		} else if (PyString_Check(argument)) {
 			PyObject* u = PyUnicode_FromObject(argument);
 			if (u == NULL) {
 		if (PyUnicode_Check(argument) && PyUnicode_GetSize(argument) == 1) {
 			*(UniChar*)datum = (UniChar)(*PyUnicode_AsUnicode(argument));
 			return 0;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		} else if (PyString_Check(argument)) {
 			PyObject* u = PyUnicode_FromObject(argument);
 			if (u == NULL) {
 	case _C_FLT:
 		if (PyFloat_Check (argument)) {
 			*(float *) datum = (float)PyFloat_AsDouble (argument);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		} else if (PyInt_Check (argument)) {
 			*(float *) datum = (float) PyInt_AsLong (argument);
 #endif
 				return -1;
 			}
 		} else if (
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 				PyString_Check(argument) || 
 #else
 				PyBytes_Check(argument) || 
 	case _C_DBL:
 		if (PyFloat_Check (argument)) {
 			*(double *) datum = PyFloat_AsDouble (argument);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		} else if (PyInt_Check (argument)) {
 			*(double *) datum = (double) PyInt_AsLong (argument);
 #endif
 				return -1;
 			}
 		} else if (
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 				PyString_Check(argument) || 
 #else
 				PyBytes_Check(argument) || 

pyobjc-core/Modules/objc/objc_util.m

 		if (bytes == NULL) {
 			return '\0';
 		}
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(typecode)) {
 		bytes = typecode; Py_INCREF(bytes);
 #endif
 			Py_INCREF(pythonList);
 			return SHOULD_IGNORE;
 		}
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (*elementType == _C_UNICHAR && PyString_Check(pythonList)) {
 		PyObject* u = PyUnicode_Decode(
 				PyString_AsString(pythonList),

pyobjc-core/Modules/objc/parsexml.m

 				v = NULL;
 
 			} else {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 				v = PyFloat_FromString(s, &end);
 #else
 				v = PyFloat_FromString(s);
+				end = NULL;
 #endif
 				Py_DECREF(s);
 			}

pyobjc-core/Modules/objc/pointer-support.m

 	return 0;
 }
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 
 static int dontClose(FILE* fp __attribute__((__unused__)))
 {
 		PyObjectPtr_New, PyObjectPtr_Convert);
 	if (r == -1) return -1;
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	r = PyObjCPointerWrapper_Register(@encode(FILE*),
 		FILE_New, FILE_Convert);
 	if (r == -1) return -1;

pyobjc-core/Modules/objc/pyobjc-api.h

 static inline PyObject*
 PyObjC_CreateInlineTab(PyObjC_function_map* map)
 {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	return PyCObject_FromVoidPtr(map, NULL);
 #else
 	return PyCapsule_New(map, "objc.__functionlist__", NULL);
 	PyObject* m;
 	PyObject* d;
 	PyObject* api_obj;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	PyObject* name = PyString_FromString("objc");
 #else
 	PyObject* name = PyUnicode_FromString("objc");
 			"No C_API in objc module");
 		return -1;
 	}
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	PyObjC_API = PyCObject_AsVoidPtr(api_obj);
 #else
 	PyObjC_API = PyCapsule_GetPointer(api_obj, "objc." PYOBJC_API_NAME);

pyobjc-core/Modules/objc/pyobjc-api.m

 
 int PyObjCAPI_Register(PyObject* module)
 {
-#if PY_VERSION_HEX <= 0x03000000
+#if PY_MAJOR_VERSION == 2
 	PyObject* API = PyCObject_FromVoidPtr(&objc_api, NULL);
 #else
 	PyObject* API = PyCapsule_New(&objc_api, "objc." PYOBJC_API_NAME, NULL);

pyobjc-core/Modules/objc/pyobjc-compat.h

 
 #endif
 
-#if PY_VERSION_HEX < 0x03000000
+#if __LP64__
+#define Py_ARG_NSInteger "l"
+#define Py_ARG_NSUInteger "L"
+#else
+#define Py_ARG_NSInteger "i"
+#define Py_ARG_NSUInteger "L"
+#endif
+
+#if PY_MAJOR_VERSION == 2
 #define Py_REFCNT(ob)           (((PyObject*)(ob))->ob_refcnt)
 #define Py_TYPE(ob)             (((PyObject*)(ob))->ob_type)
 #define Py_SIZE(ob)             (((PyVarObject*)(ob))->ob_size)
 #define PyCapsule_CheckExact(object)	PyCObject_Check(object)
 #endif
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 
 #define PyErr_Format PyObjCErr_Format
 
 
 #endif
 
-#if PY_VERSION_HEX >= 0x03000000
+#if PY_MAJOR_VERSION == 3
 #define PyInt_FromLong		PyLong_FromLong
 #define PyInt_FromString	PyLong_FromString
 

pyobjc-core/Modules/objc/pyobjc-compat.m

 #include "pyobjc.h"
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 
 PyObject* 
 PyObjCString_InternFromStringAndSize(const char* v, Py_ssize_t l)

pyobjc-core/Modules/objc/pyobjc.h

 #include "OC_PythonDictionary.h"
 #include "OC_PythonUnicode.h"
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 #include "OC_PythonString.h"
 #endif
 
 extern BOOL PyObjC_nativeProperties;
 extern int PyObjC_VerboseLevel;
 extern int PyObjC_HideProtected;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 extern int PyObjC_StrBridgeEnabled;
 #endif
 extern PyObject *PyObjCStrBridgeWarning;

pyobjc-core/Modules/objc/registry.m

 			}
 			cur_class = objc_lookUpClass(PyBytes_AsString(bytes));
 			Py_DECREF(bytes);
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		} else if (PyString_Check(nm)) {
 			cur_class = objc_lookUpClass(PyString_AsString(nm));
 #else

pyobjc-core/Modules/objc/selector.m

 	if (sel->sel_self == NULL) {
 		rval = PyText_FromFormat("<unbound native-selector %s in %s>", sel_getName(sel->sel_selector), class_getName(sel->sel_class));
 	} else {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		PyObject* selfrepr = PyObject_Repr(sel->sel_self);
 		if (selfrepr == NULL) {
 			return NULL;
 
 		myClass = PyObjCClass_New(self->sel_class);
 		if (!(PyObject_IsInstance(pyself, myClass)
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			|| (PyString_Check(pyself) && class_isSubclassOf(self->sel_class, [NSString class])) 
 #endif
 			|| (PyUnicode_Check(pyself) && class_isSubclassOf(self->sel_class, [NSString class])) 
 	} else {
 		/* Should not happen... */
 		result->argcount = 0;
-		char* s = sel_getName(selector);
+		const char* s = sel_getName(selector);
 		while ((s = strchr(s, ':')) != NULL) {
 			result->argcount++;
 			s++;
 			rval = PyText_FromFormat("<unbound selector %s at %p>", sel_getName(sel->sel_selector), sel);
 		}
 	} else {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		PyObject* selfrepr = PyObject_Repr(sel->sel_self);
 		if (selfrepr == NULL) {
 			return NULL;
 		Py_DECREF(bytes);
 
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(name)) {
 		strncpy(buf, PyString_AS_STRING(name), sizeof(buf)-1);
 #endif
 			return NULL;
 		}
 		
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		callable = PyObject_GetAttrString(tmp, "im_func");
 #else
 		callable = PyObject_GetAttrString(tmp, "__funct__");
 			return callable;
 		}
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		callable = PyObject_GetAttrString(tmp, "im_func");
 #else
 		callable = PyObject_GetAttrString(tmp, "__func__");
 					PyBytes_AsString(bytes));
 			Py_DECREF(bytes);
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		} else if (PyString_Check(pyname)) {
 			selector = PyObjCSelector_DefaultSelector(
 					PyString_AsString(pyname));
 				PyBytes_AsString(bytes));
 		Py_DECREF(bytes);
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	} else if (PyString_Check(pyname)) {
 		selector = PyObjCSelector_DefaultSelector(
 			PyString_AS_STRING(pyname));

pyobjc-core/Modules/objc/struct-wrapper.m

 	return result;
 }
 
+static PyObject*
+struct_mp_subscript(PyObject* self, PyObject* item)
+{
+	if (PyIndex_Check(item)) {
+		Py_ssize_t i;
+		i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+		if (i == -1 && PyErr_Occurred()) {
+			return NULL;
+		} 
+		if (i < 0) {
+			i += struct_sq_length(self);
+		}
+		return struct_sq_item(self, i);
+	} else if (PySlice_Check(item)) {
+		Py_ssize_t start, stop, step, slicelength, cur, i;
+		PyObject* result;
+		PyObject* it;
+
+		if (PySlice_GetIndicesEx((PySliceObject*)item, 
+				struct_sq_length(self),
+				&start, &stop, &step, &slicelength) < 0) {
+			return NULL;
+		}
+
+		if (slicelength <= 0) {
+			return PyTuple_New(0);
+		} else if (step == 1) {
+			return struct_sq_slice(self, start, stop);
+		} else {
+			result = PyTuple_New(slicelength);
+			if (result == NULL) {
+				return NULL;
+			}
+
+			for (cur = start, i = 0; i < slicelength; 
+						cur += step, i++) {
+				it = struct_sq_item(self, cur);
+				PyTuple_SET_ITEM(result, i, it);
+			}
+			return result;
+		}
+
+	} else {
+		PyErr_Format(PyExc_TypeError,
+			"struct indices must be integers, not %.200s",
+			Py_TYPE(item)->tp_name);
+		return NULL;
+	}
+}
+
+static int
+struct_mp_ass_subscript(PyObject* self, PyObject* item, PyObject* value)
+{
+	if (PyIndex_Check(item)) {
+		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+		if (i == -1 && PyErr_Occurred()) {
+			return -1;
+		} 
+		if (i < 0) {
+			i += struct_sq_length(self);
+		}
+		return struct_sq_ass_item(self, i, value);
+	} else if (PySlice_Check(item)) {
+		Py_ssize_t start, stop, step, slicelength;
+
+		if (PySlice_GetIndicesEx((PySliceObject*)item, 
+				struct_sq_length(self), &start, &stop,
+				&step, &slicelength) < 0) {
+			return -1;
+		}
+		if (step == 1) {
+			return struct_sq_ass_slice(self, start, stop, value);
+		}
+
+		if (value == NULL) {
+			PyErr_Format(PyExc_TypeError,
+				"Cannot delete items in an %s instance",
+				Py_TYPE(self)->tp_name);
+			return -1;
+		}
+
+		PyObject* seq = PySequence_Fast(value, 
+				"must assign sequence to slice");
+		if (seq == NULL) return -1;
+
+		if (PySequence_Fast_GET_SIZE(seq) != slicelength) {
+			Py_DECREF(seq);
+			PyErr_Format(PyExc_TypeError,
+				"slice assignment would change size of %s "
+				"instance", Py_TYPE(self)->tp_name);
+			return -1;
+		}
+
+		Py_ssize_t cur, i;
+		for (cur = start, i = 0; i < slicelength; cur += step, i++) {
+			int r = struct_sq_ass_item(self, cur, 
+				PySequence_Fast_GET_ITEM(seq, i));
+			if (r == -1) {
+				Py_DECREF(seq);
+				return -1;
+			}
+		}
+
+		Py_DECREF(seq);
+		return 0;
+	} else {
+		PyErr_Format(PyExc_TypeError,
+			"struct indices must be integers, not %.200s",
+			Py_TYPE(item)->tp_name);
+		return -1;
+	}
+}
+
+
 static PySequenceMethods struct_as_sequence = {
 	struct_sq_length,	/* sq_length */
 	NULL,			/* sq_concat */
 	NULL			/* sq_inplace_repeat */
 };
 
+static PyMappingMethods struct_as_mapping = {
+	struct_sq_length,
+	struct_mp_subscript,
+	struct_mp_ass_subscript,
+};
+
 static PyMethodDef struct_methods[] = {
 	{
 		"__reduce__", 
 		return;
 	}
 
-
 	if (args != NULL && !PyTuple_Check(args)) {
 		PyErr_Format(PyExc_TypeError, 
 				"%s() argument tuple is not a tuple",
 
 		keys = PyDict_Keys(kwds);
 		if (keys == NULL) {
-			Py_DECREF(keys);
+			*(int*)retval = -1;
+			return;
 		}
 
 		if (!PyList_Check(keys)) {
 				k_bytes = PyUnicode_AsEncodedString(k, NULL, NULL);
 				if (k_bytes == NULL) {
 					*(int*)retval = -1;
+					return;
 				}
-				return;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 			} else if (PyString_Check(k)) {
 				k_bytes = k; Py_INCREF(k_bytes);
 #endif
 	struct_repr,				/* tp_repr */
 	0,					/* tp_as_number */
 	&struct_as_sequence,			/* tp_as_sequence */
-	0,					/* tp_as_mapping */
+	&struct_as_mapping,			/* tp_as_mapping */
 	struct_hash,				/* tp_hash */
 	0,					/* tp_call */
 	0,					/* tp_str */
 	struct_setattro,			/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		| Py_TPFLAGS_HAVE_RICHCOMPARE 
 #endif
 		| Py_TPFLAGS_HAVE_GC, 		/* tp_flags */

pyobjc-core/Modules/objc/super-call.m

 	return 0;
 }
 
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 
 static void memblock_capsule_cleanup(void* ptr, void* closure __attribute__((__unused__)))
 {
 		
 		if (
 			(PyUnicode_Check(pysel) && PyObjC_is_ascii_string(pysel, sel_getName(sel)))
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 		     || (PyString_Check(pysel) && strcmp(PyString_AsString(pysel), sel_getName(sel)) == 0)
 #else
 		     || (PyBytes_Check(pysel) && strcmp(PyBytes_AsString(pysel), sel_getName(sel)) == 0)
 	PyObject* self, 
 	PyObject* args __attribute__((__unused__)))
 {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION == 2
 	PyObject* repr;
 
 	repr = PyObject_Repr(self);

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

 #if 0
 //#if !defined(__OBJC2__) && (PY_VERSION_HEX < 0x03000000)
 #endif
-#if (PY_VERSION_HEX < 0x03000000)
+#if PY_MAJOR_VERSION == 2
 	int r;
 
 	/* Fall back to MacPython CFType support: */
 PyObjC_IDToCFType(id argument __attribute__((__unused__)))
 {
 
-#if !defined(__OBJC2__) && (PY_VERSION_HEX < 0x03000000)
+#if !defined(__OBJC2__) && (PY_MAJOR_VERSION == 2)
 	CFTypeRef typeRef = (CFTypeRef)argument;
 	CFTypeID typeID = CFGetTypeID(argument);
 

pyobjc-core/Modules/objc/unicode-object.m

 
 
 	result->base.hash = -1;
-#if PY_VERSION_HEX >= 0x03000000
+#if PY_MAJOR_VERSION == 3
 	result->base.state = 0;
 #endif
 	result->base.defenc = NULL;

pyobjc-core/setup.py

             from PyObjCTest.loader import makeTestSuite
             import unittest
            
-            print (sys.path)
             unittest.main(None, None, [unittest.__file__]+self.test_args)
 
 from setuptools.command import egg_info as orig_egg_info
             list(glob.glob(os.path.join('Modules', 'objc', '*.m'))),
             extra_compile_args=CFLAGS + ["-I/usr/include/ffi"],
             extra_link_args=OBJC_LDFLAGS + ["-lffi"],
+            depends=list(glob.glob(os.path.join('Modules', 'objc', '*.h'))),
         ),
     ]
 
             FFI_SOURCE + list(glob.glob(os.path.join('Modules', 'objc', '*.m'))),
             extra_compile_args=CFLAGS + FFI_CFLAGS,
             extra_link_args=OBJC_LDFLAGS,
+            depends=list(glob.glob(os.path.join('Modules', 'objc', '*.h'))),
         ),
     ]