Commits

Ronald Oussoren  committed d5b7186

Merged revisions 2571-2574 via svnmerge from
https://svn.red-bean.com/pyobjc/trunk/pyobjc

........
r2571 | ronaldoussoren | 2010-08-13 08:10:41 +0200 (Fri, 13 Aug 2010) | 16 lines

This fixes a number of small issues:

* The wrappers for the NSBitmapImagerep initializers were incomplete, now both methods
that take bitmap plane arguments are implemented and work.

* Fix issue with cfmessage port wrappers

* Remove debug print statuements

All of this is tested on python 2.7 and will be backported to 2.3.1 once I've finished
testing.

With this patch all tests pass, although the cfrunloop and cfusernotification tests still
fail most of the time when running the entire suite. This is probably related to how I set up
the loop and clean up resources, the tests run fine when running those test modules seperately.
........
r2572 | ronaldoussoren | 2010-08-13 13:17:27 +0200 (Fri, 13 Aug 2010) | 5 lines

Some small test changes that seem to ensure that these tests pass
reliably.

The actual change is a hack, but good enough for the test cases.
........
r2573 | ronaldoussoren | 2010-08-13 16:03:40 +0200 (Fri, 13 Aug 2010) | 1 line

Remove debug print from tests, re-enable a test that turns out to work just fine
........
r2574 | ronaldoussoren | 2010-08-15 11:56:31 +0200 (Sun, 15 Aug 2010) | 5 lines

* All tests now pass

* Added tests and metadata for a couple of functions that weren't available
yet.
........

  • Participants
  • Parent commits a9c9308
  • Branches pyobjc-2.3.x

Comments (0)

Files changed (20)

File pyobjc-framework-Cocoa/Doc/api-notes-CoreFoundation.txt

 * ``CFMessagePortSetDispatchQueue``: not supported yet because there
   are no wrappers for dispatch_queue_t yet.
 
+* ``CFMessagePortInvalidationCallback``: The second argument of the 
+  callback is an integer that should be ignored. The context value
+  can be retrieved using ``CFMessagePortGetContext`` (for local
+  ports, remote ports don't have a context).
+
 CFNumber
 --------
 

File pyobjc-framework-Cocoa/Lib/CoreFoundation/PyObjC.bridgesupport

   <function name='CFMessagePortGetInvalidationCallBack'>
     <retval function_pointer='true' type='^?' type64='^?'>
       <arg type='@' />
-      <arg type='@' />
+      <arg type='^v' />
     </retval>
     <arg type='^{__CFMessagePort=}' />
   </function>
     <arg type='^{__CFMessagePort=}' />
     <arg function_pointer='true' type='^?' type64='^?'>
       <arg type='@' />
-      <arg type='@' />
+      <arg type='^v' />
     </arg>
   </function>
   <function name='CFMessagePortSetName'>

File pyobjc-framework-Cocoa/Modules/_AppKit_nsbitmap.m

 	return result;
 }
 
-#if 0
-static PyObject*
-call_NSBitmapImageRep_initWithBitmapDataPlanes_bitmapFormat(
-		PyObject* method, PyObject* self, PyObject* arguments)
-{
-	PyObject* py_planes;
-	unsigned char** planes;
-	Py_ssize_t  nr_planes;
-	PyObject* py_width;
-	NSInteger width;
-	PyObject* py_height;
-	NSInteger height;
-	long	  bitsPerSample;
-	long	  samplesPerPixel;
-	PyObject* py_hasAlpha;
-	BOOL	  hasAlpha;
-	PyObject* py_isPlanar;
-	BOOL	  isPlanar;
-	PyObject* py_colorSpaceName;
-	NSString* colorSpaceName;
-	long	  bitmapFormat;
-	PyObject* py_bytesPerRow;
-	NSInteger bytesPerRow;
-	PyObject* py_bitsPerPixel;
-	NSInteger bitsPerPixel;
-
-	if (!PyArg_Parse(args, "OOOiiOOOiOO", 
-		&py_planes, &py_width, &py_height, &bitsPerSample,
-		&samplesPerPixel, &py_hasAlpha, &py_isPlanar,
-		&bitmapFormat, &py_bytesPerRow, &py_bitsPerPixel)) {
-
-		return NULL;
-	}
-
-	if (PyObjC_PythonToObjC(@encode(NSInteger), py_width, &width) == -1) {
-		return NULL;
-	}
-	if (PyObjC_PythonToObjC(@encode(NSInteger), py_height, &height) == -1) {
-		return NULL;
-	}
-	hasAlpha = PyObject_IsTrue(py_hasAlpha);
-	isPlanar = PyObject_IsTrue(py_isPlanar);
-	if (PyObjC_PythonToObjC(@encode(NSInteger), py_bytesPerRow, &bytesPerRow) == -1) {
-		return NULL;
-	}
-	if (PyObjC_PythonToObjC(@encode(NSInteger), py_bitsPerPixel, &bitsPerPixel) == -1) {
-		return NULL;
-	}
-
-	if (py_planes == Py_None) {
-		planes = NULL;
-		nr_planes = -1;
-	} else {
-		PyObject* seq = PySequence_Fast(py_planes,
-				"Planes must be sequence");
-		if (seq == NULL) {
-			return NULL;
-		}
-		nr_planes = PySequence_Fast_GET_SIZE(seq);
-
-		planes = malloc(sizeof(unsigned char*) * nr_planes);
-		if (planes == NULL) {
-			PyErr_NoMemory();
-			Py_DECREF(seq);
-			return NULL;
-		}
-
-		Py_ssize_t i;
-		for (i = 0; i < nr_planes; i++) {
-
-		}
-	}
-}
-#endif
-
-
-/* XXX: Needs looking into, argument parsing seems awfully complex */
 static PyObject*
 call_NSBitmapImageRep_initWithBitmap(PyObject* method, 
 		PyObject* self, PyObject* arguments)
 {
 	PyObject* result;
 	PyObject* maybeNone;
-	unsigned char *dataPlanes[5];
+	const void *dataPlanes[5];
 	int garbage;
 	int width, height;
 	int bps, spp;
 	BOOL hasAlpha, isPlanar;
 	char *colorSpaceName;
 	NSString *colorSpaceNameString;
-	int bpr, bpp;
+	int bpr, bpp, i;
 	NSBitmapImageRep *newImageRep;
 	struct objc_super super;
+	PyObject*  py_Planes[5];
+	Py_buffer  planeBuffers[5];
+
+	for (i = 0; i < 5; i++) {
+		py_Planes[i] = NULL;
+		planeBuffers[i].buf = NULL;
+	}
 
 	// check for five well defined read buffers in data planes argument
-	if (!PyArg_ParseTuple(arguments, "("Py_ARG_BYTES"#"Py_ARG_BYTES"#"Py_ARG_BYTES"#"Py_ARG_BYTES"#"Py_ARG_BYTES"#)iiiibbsii",
-		&dataPlanes[0], &garbage,
-		&dataPlanes[1], &garbage,
-		&dataPlanes[2], &garbage,
-		&dataPlanes[3], &garbage,
-		&dataPlanes[4], &garbage,
+	if (!PyArg_ParseTuple(arguments, "(OOOOO)iiiibbsii",
+		py_Planes + 0,
+		py_Planes + 1,
+		py_Planes + 2,
+		py_Planes + 3,
+		py_Planes + 4,
 		&width,
 		&height,
 		&bps,
 
 		PyErr_Clear();
 		bzero(dataPlanes, sizeof(dataPlanes));
+		bzero(py_Planes, sizeof(py_Planes));
 
 		if (!PyArg_ParseTuple(arguments, "Oiiiibbsii",
 				 &maybeNone,
 				return NULL;
 			}
 		}
+	} else {
+		for (i = 0; i < 5; i++) {
+			if (py_Planes[i] == Py_None) {
+				dataPlanes[i] = NULL;
+			} else {
+				int r = PyObject_GetBuffer(py_Planes[i], planeBuffers + i,
+						PyBUF_SIMPLE);
+				if (r == 0) {
+					dataPlanes[i] = planeBuffers[i].buf;
+				} else {
+#if PY_MAJOR_VERSION == 2
+					/* Fall back to old-style buffers, not all python 2 types 
+					 * implement the newer APIs and that includes the stdlib.
+					 */
+					PyErr_Clear();
+					void * buf;
+					Py_ssize_t len;
+					int r = PyObject_AsReadBuffer(py_Planes[i], 
+						&buf, &len);
+					if (r == -1) {
+						goto error_cleanup;
+					}
+					dataPlanes[i] = buf;
+#else
+					goto error_cleanup;
+#endif
+				}
+			}
+		}
 	}
 
 	colorSpaceNameString = [NSString stringWithUTF8String: colorSpaceName];
 			PyObjCSelector_GetClass(method),
 			PyObjCObject_GetObject(self));
     
-		newImageRep = ((id(*)(struct objc_super*, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, BOOL, BOOL, id, NSInteger, NSInteger))objc_msgSendSuper)(&super,
+		newImageRep = ((id(*)(struct objc_super*, SEL, const void**, NSInteger, NSInteger, NSInteger, NSInteger, BOOL, BOOL, id, NSInteger, NSInteger))objc_msgSendSuper)(&super,
 				PyObjCSelector_GetSelector(method),
 				dataPlanes, width, height, bps, spp, 
 				hasAlpha, isPlanar, colorSpaceNameString, 
 		newImageRep = nil;
 	PyObjC_ENDHANDLER
 
+	for (i = 0; i < 5; i++) {
+		if (py_Planes[i] != NULL && planeBuffers[i].buf != NULL) {
+			PyBuffer_Release(&planeBuffers[i]);
+		}
+	}
+
 	if (newImageRep == nil && PyErr_Occurred()) {
 		return NULL;
 	}
 	result = PyObjC_IdToPython(newImageRep);
 
 	return result;
+
+error_cleanup:
+	{
+		int j = i;
+		for (i = 0; i < j; i++) {
+			if (py_Planes[i] != NULL && planeBuffers[i].buf != NULL) {
+				PyBuffer_Release(&planeBuffers[i]);
+			}
+		}
+	}
+	return NULL;
+}
+
+static PyObject*
+call_NSBitmapImageRep_initWithBitmapFormat(PyObject* method, 
+		PyObject* self, PyObject* arguments)
+{
+	PyObject* result;
+	PyObject* maybeNone;
+	const void *dataPlanes[5];
+	int garbage;
+	int width, height;
+	int bps, spp;
+	BOOL hasAlpha, isPlanar;
+	char *colorSpaceName;
+	NSString *colorSpaceNameString;
+	int bpr, bpp, i;
+	NSBitmapImageRep *newImageRep;
+	int format;
+	struct objc_super super;
+	PyObject*  py_Planes[5];
+	Py_buffer  planeBuffers[5];
+
+	for (i = 0; i < 5; i++) {
+		py_Planes[i] = NULL;
+		planeBuffers[i].buf = NULL;
+	}
+
+	// check for five well defined read buffers in data planes argument
+	if (!PyArg_ParseTuple(arguments, "(OOOOO)iiiibbsiii",
+		py_Planes + 0,
+		py_Planes + 1,
+		py_Planes + 2,
+		py_Planes + 3,
+		py_Planes + 4,
+		&width,
+		&height,
+		&bps,
+		&spp,
+		&hasAlpha,
+		&isPlanar,
+		&colorSpaceName,
+		&format,
+		&bpr,
+		&bpp)) {
+
+		if ( !PyErr_ExceptionMatches(PyExc_TypeError) ) {
+			return NULL;
+		}
+
+		PyErr_Clear();
+		bzero(dataPlanes, sizeof(dataPlanes));
+		bzero(py_Planes, sizeof(py_Planes));
+
+		if (!PyArg_ParseTuple(arguments, "Oiiiibbsiii",
+				 &maybeNone,
+				 &width,
+				 &height,
+				 &bps,
+				 &spp,
+				 &hasAlpha,
+				 &isPlanar,
+				 &colorSpaceName,
+				 &format,
+				 &bpr,
+				 &bpp)){
+
+			return NULL; //! any other situations that we need to parse specific args go here
+		} else {
+			// first arg must be none as nothing else makes sense
+			if (maybeNone != Py_None) {
+				PyErr_SetString(PyExc_TypeError, "First argument must be a 5 element Tuple or None.");
+				return NULL;
+			}
+		}
+	} else {
+		for (i = 0; i < 5; i++) {
+			if (py_Planes[i] == Py_None) {
+				dataPlanes[i] = NULL;
+			} else {
+				int r = PyObject_GetBuffer(py_Planes[i], planeBuffers + i,
+						PyBUF_SIMPLE);
+				if (r == 0) {
+					dataPlanes[i] = planeBuffers[i].buf;
+				} else {
+#if PY_MAJOR_VERSION == 2
+					/* Fall back to old-style buffers, not all python 2 types 
+					 * implement the newer APIs and that includes the stdlib.
+					 */
+					PyErr_Clear();
+					void * buf;
+					Py_ssize_t len;
+					int r = PyObject_AsReadBuffer(py_Planes[i], 
+						&buf, &len);
+					if (r == -1) {
+						goto error_cleanup;
+					}
+					dataPlanes[i] = buf;
+#else
+					goto error_cleanup;
+#endif
+				}
+			}
+		}
+	}
+
+	colorSpaceNameString = [NSString stringWithUTF8String: colorSpaceName];
+
+	PyObjC_DURING
+		PyObjC_InitSuper(&super,
+			PyObjCSelector_GetClass(method),
+			PyObjCObject_GetObject(self));
+    
+		newImageRep = ((id(*)(struct objc_super*, SEL, const void**, NSInteger, NSInteger, NSInteger, NSInteger, BOOL, BOOL, id, NSBitmapFormat, NSInteger, NSInteger))objc_msgSendSuper)(&super,
+				PyObjCSelector_GetSelector(method),
+				dataPlanes, width, height, bps, spp, 
+				hasAlpha, isPlanar, colorSpaceNameString, 
+				(NSBitmapFormat)format, bpr, bpp);
+
+	PyObjC_HANDLER
+		PyObjCErr_FromObjC(localException);
+		result = NULL;
+		newImageRep = nil;
+	PyObjC_ENDHANDLER
+
+	for (i = 0; i < 5; i++) {
+		if (py_Planes[i] != NULL && planeBuffers[i].buf != NULL) {
+			PyBuffer_Release(&planeBuffers[i]);
+		}
+	}
+
+	if (newImageRep == nil && PyErr_Occurred()) {
+		return NULL;
+	}
+
+	result = PyObjC_IdToPython(newImageRep);
+
+	return result;
+
+error_cleanup:
+	{
+		int j = i;
+		for (i = 0; i < j; i++) {
+			if (py_Planes[i] != NULL && planeBuffers[i].buf != NULL) {
+				PyBuffer_Release(&planeBuffers[i]);
+			}
+		}
+	}
+	return NULL;
 }
 
 
 				PyObject* buffer = PyBuffer_FromReadWriteMemory(dataPlanes[i], bytesPerPlane);
 #else
 				Py_buffer info;
-				if (PyBuffer_FillInfo(&info, NULL, dataPlanes[i], bytesPerPlane, 1, PyBUF_FULL) < 0) {
+				if (PyBuffer_FillInfo(&info, NULL, dataPlanes[i], bytesPerPlane, 0, PyBUF_FULL) < 0) {
 					return NULL;
 				}
 				PyObject* buffer = PyMemoryView_FromBuffer(&info);
 			PyObjCSelector_GetClass(method),
 			PyObjCObject_GetObject(self));
     
-		bitmapData = (unsigned char *) objc_msgSendSuper(&super, 
+		bitmapData = (unsigned char *(*)(id, SEL)) objc_msgSendSuper(&super, 
 				PyObjCSelector_GetSelector(method));
 			
 		bytesPerPlane = [
 		return NULL;
 	}
 
-#if  PY_VERSION_HEX <= 0x02069900 
+#if  PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
 	result = PyBuffer_FromReadWriteMemory(bitmapData, bytesPerPlane);
 #else
+
 	/* A memory view requires that the backing store implements the buffer
 	 * interface, therefore create a mutable bytes object to do that for us.
 	 */
 	Py_buffer info;
+#if 0
 	NSMutableData* data = [[NSMutableData alloc] initWithBytesNoCopy:bitmapData length: bytesPerPlane freeWhenDone:NO];
 	PyObject* bytesBuf = PyObjC_ObjCToPython("@", &data);
 	[data release];
 	}
 
 	if (PyBuffer_FillInfo(&info, bytesBuf, bitmapData, bytesPerPlane, 0, PyBUF_FULL) < 0) {
+#endif
+	if (PyBuffer_FillInfo(&info, NULL, bitmapData, bytesPerPlane, 0, PyBUF_FULL) < 0) {
 		return NULL;
 	}
 	result = PyMemoryView_FromBuffer(&info);
 
 	if (PyObjC_RegisterMethodMapping(
 			class_NSBitmapImageRep,
+			@selector(initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:),
+			call_NSBitmapImageRep_initWithBitmapFormat,
+			PyObjCUnsupportedMethod_IMP) < 0) {
+
+		return -1;
+	}
+
+	if (PyObjC_RegisterMethodMapping(
+			class_NSBitmapImageRep,
 			@selector(getBitmapDataPlanes:),
 			call_NSBitmapImageRep_getBitmapDataPlanes_,
 			PyObjCUnsupportedMethod_IMP) < 0) {

File pyobjc-framework-Cocoa/Modules/_Foundation_data.m

 	result = PyBuffer_FromMemory((char*)bytes, bytes_len);
 #else
 	/* 2.7 or later: use a memory view */
-	printf("\n-data %p\n", bytes);
 	Py_buffer info;
 	if (PyBuffer_FillInfo(&info, self, (void*)bytes, bytes_len, 1, PyBUF_FULL_RO) < 0) {
 		return NULL;
 	}
 	result = PyMemoryView_FromBuffer(&info);
-	printf("-> %s\n", PyObject_REPR(result));
 #endif
 
 	return result;

File pyobjc-framework-Cocoa/PyObjCTest/test_cfmessageport.py

 
     def testTypeID(self):
         self.assertIsInstance(CFMessagePortGetTypeID(), (int, long))
+
     def testInteraction(self):
-        self.fail("research")
         class Context: pass
         context = Context()
 
         def callout(port, messageid, data, info):
             pass
-
         port, shouldFree = CFMessagePortCreateLocal(None, u"name", callout, context, None)
         self.assertIsInstance(port, CFMessagePortRef)
         self.assertIs(shouldFree is True or shouldFree, False)
         self.assertFalse(CFMessagePortIsRemote(port))
         ctx = CFMessagePortGetContext(port, None)
         self.assertIs(ctx, context)
-        port = CFMessagePortCreateRemote(None, u"name")
-        self.assertIsInstance(port, CFMessagePortRef)
+
+        port2 = CFMessagePortCreateRemote(None, u"name")
+        self.assertIsInstance(port2, CFMessagePortRef)
         self.assertResultIsBOOL(CFMessagePortIsRemote)
-        self.assertTrue(CFMessagePortIsRemote(port))
-        self.assertTrue(CFMessagePortGetName(port), u"name")
+        self.assertTrue(CFMessagePortIsRemote(port2))
+        self.assertTrue(CFMessagePortGetName(port2), u"name")
 
-        CFMessagePortSetName(port, "newname")
-        self.assertTrue(CFMessagePortGetName(port), u"newname")
+
+        CFMessagePortSetName(port2, "newname")
+        self.assertTrue(CFMessagePortGetName(port2), u"newname")
 
         cb = CFMessagePortGetInvalidationCallBack(port)
         self.assertIs(cb, None)

File pyobjc-framework-Cocoa/PyObjCTest/test_cfnumber.py

         self.assertEqual(v , kCFNumberDoubleType)
         v = CFNumberGetByteSize(44)
 
-        self.assertEqual(v , 8)
+        if sys.maxint >= 2**32:
+            self.assertEqual(v , 8)
+        else:
+            self.assertEqual(v , 4)
         v = CFNumberGetByteSize(44.0)
         self.assertEqual(v , 8)
         self.assertFalse(CFNumberIsFloatType(44))

File pyobjc-framework-Cocoa/PyObjCTest/test_cfrunloop.py

         self.assertIsInstance(CFRunLoopObserverGetTypeID(), (int, long))
         self.assertIsInstance(CFRunLoopTimerGetTypeID(), (int, long))
     def testRunloop(self):
+        runloop_mode = kCFRunLoopDefaultMode
+        runloop_mode = "pyobjctest.cfrunloop"
+
         loop = CFRunLoopGetCurrent()
         self.assertIsInstance(loop, CFRunLoopRef)
         loop = CFRunLoopGetMain()
         CFRunLoopAddCommonMode(loop, "pyobjctest")
         allmodes = CFRunLoopCopyAllModes(loop)
 
-        tm = CFRunLoopGetNextTimerFireDate(loop, kCFRunLoopDefaultMode)
+        tm = CFRunLoopGetNextTimerFireDate(loop, runloop_mode)
         self.assertIsInstance(tm, float)
         b = CFRunLoopIsWaiting(loop)
         self.assertIsInstance(b, bool)
 
         # CFRunLoopRun is hard to test reliably
         self.assertHasAttr(CoreFoundation, 'CFRunLoopRun')
+
     def testObserver(self):
+        runloop_mode = kCFRunLoopDefaultMode
+        runloop_mode = "pyobjctest.cfrunloop"
 
         rl = CFRunLoopGetCurrent()
 
         observer = CFRunLoopObserverCreate(None, kCFRunLoopEntry|kCFRunLoopExit,
                 True, 4, callback, data)
         self.assertIsInstance(observer, CFRunLoopObserverRef)
-        self.assertIs(CFRunLoopContainsObserver(rl, observer, kCFRunLoopDefaultMode), False)
-        CFRunLoopAddObserver(rl, observer, kCFRunLoopDefaultMode)
-        self.assertIs(CFRunLoopContainsObserver(rl, observer, kCFRunLoopDefaultMode), True)
+        self.assertIs(CFRunLoopContainsObserver(rl, observer, runloop_mode), False)
+        CFRunLoopAddObserver(rl, observer, runloop_mode)
+        self.assertIs(CFRunLoopContainsObserver(rl, observer, runloop_mode), True)
 
         # Use dummy stream to ensure that the runloop actually performs work
         strval = b'hello world'
         stream = CFReadStreamCreateWithBytesNoCopy(None,
                                 strval, len(strval), kCFAllocatorNull)
         self.assertIsInstance(stream, CFReadStreamRef)
-        CFReadStreamScheduleWithRunLoop(stream, rl, kCFRunLoopDefaultMode)
-        res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, True)
-        CFReadStreamUnscheduleFromRunLoop(stream, rl, kCFRunLoopDefaultMode)
+        CFReadStreamScheduleWithRunLoop(stream, rl, runloop_mode)
+        res = CFRunLoopRunInMode(runloop_mode, 1.0, True)
+        CFReadStreamUnscheduleFromRunLoop(stream, rl, runloop_mode)
         
         self.assertNotEqual(len(state) , 0 )
         for item in state:
             self.assertIs(item[0], observer)
             self.assertIsIn(item[1], (kCFRunLoopEntry, kCFRunLoopExit))
             self.assertIs(item[2], data)
-        CFRunLoopRemoveObserver(rl, observer, kCFRunLoopDefaultMode)
-        self.assertIs(CFRunLoopContainsObserver(rl, observer, kCFRunLoopDefaultMode), False)
+        CFRunLoopRemoveObserver(rl, observer, runloop_mode)
+        self.assertIs(CFRunLoopContainsObserver(rl, observer, runloop_mode), False)
 
 
     def testTimer(self):
+        runloop_mode = kCFRunLoopDefaultMode
+        runloop_mode = "pyobjctest.cfrunloop"
         rl = CFRunLoopGetCurrent()
 
         state = []
         self.assertIs(CFRunLoopTimerIsValid(timer), False)
         self.assertIs(CFRunLoopTimerGetContext(timer, None), objc.NULL)
         timer = CFRunLoopTimerCreate(None, 0, 0.5, 0, 0, callback, data)
-        self.assertIs(CFRunLoopContainsTimer(rl, timer, kCFRunLoopDefaultMode), False)
-        CFRunLoopAddTimer(rl, timer, kCFRunLoopDefaultMode)
-        self.assertIs(CFRunLoopContainsTimer(rl, timer, kCFRunLoopDefaultMode), True)
-        res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 2.0, True)
+        self.assertIs(CFRunLoopContainsTimer(rl, timer, runloop_mode), False)
+        CFRunLoopAddTimer(rl, timer, runloop_mode)
+        self.assertIs(CFRunLoopContainsTimer(rl, timer, runloop_mode), True)
+        res = CFRunLoopRunInMode(runloop_mode, 1.3, True)
 
-        CFRunLoopRemoveTimer(rl, timer, kCFRunLoopDefaultMode)
-        self.assertIs(CFRunLoopContainsTimer(rl, timer, kCFRunLoopDefaultMode), False)
+        CFRunLoopTimerInvalidate(timer)
+        CFRunLoopRemoveTimer(rl, timer, runloop_mode)
+        self.assertIs(CFRunLoopContainsTimer(rl, timer, runloop_mode), False)
         self.assertFalse(len(state) < 3)
         for item in state:
             self.assertIs(item[0], timer)
             self.assertIs(item[1], data)
     def testSource(self):
+        runloop_mode = kCFRunLoopDefaultMode
+        runloop_mode = "pyobjctest.cfrunloop"
+
         rl = CFRunLoopGetCurrent()
         
         state = []
         source = CFRunLoopSourceCreate(None, 55, 
                 (0, schedule, cancel, perform, data))
         self.assertIsInstance(source, CFRunLoopSourceRef)
-        self.assertIs(CFRunLoopContainsSource(rl, source, kCFRunLoopDefaultMode), False)
-        CFRunLoopAddSource(rl, source, kCFRunLoopDefaultMode)
-        self.assertIs(CFRunLoopContainsSource(rl, source, kCFRunLoopDefaultMode), True)
+        self.assertIs(CFRunLoopContainsSource(rl, source, runloop_mode), False)
+        CFRunLoopAddSource(rl, source, runloop_mode)
+        self.assertIs(CFRunLoopContainsSource(rl, source, runloop_mode), True)
         self.assertEqual(len(state) , 1)
         self.assertEqual(state[0][0] , 'schedule')
         self.assertIs(state[0][1], data)
         self.assertIs(state[0][2], rl)
-        self.assertEqual(state[0][3] , kCFRunLoopDefaultMode)
+        self.assertEqual(state[0][3] , runloop_mode)
         del state[:]
 
-        res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, True)
+        res = CFRunLoopRunInMode(runloop_mode, 0.5, True)
         self.assertIsInstance(res, (int, long))
         #self.assertEqual(res, kCFRunLoopRunTimedOut)
 
 
         CFRunLoopSourceSignal(source)
 
-        res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, True)
+        res = CFRunLoopRunInMode(runloop_mode, 0.5, True)
         self.assertIsInstance(res, (int, long))
         self.assertEqual(res, kCFRunLoopRunHandledSource)
 
         self.assertIs(state[0][1], data)
         del state[:]
 
-        CFRunLoopRemoveSource(rl, source, kCFRunLoopDefaultMode)
-        self.assertIs(CFRunLoopContainsSource(rl, source, kCFRunLoopDefaultMode), False)
+        CFRunLoopRemoveSource(rl, source, runloop_mode)
+        self.assertIs(CFRunLoopContainsSource(rl, source, runloop_mode), False)
         self.assertEqual(len(state), 1)
         self.assertEqual(state[0][0] , 'cancel')
         self.assertIs(state[0][1], data)
         self.assertIs(state[0][2], rl)
-        self.assertEqual(state[0][3] , kCFRunLoopDefaultMode)
+        self.assertEqual(state[0][3] , runloop_mode)
     @min_os_level('10.6')
     def testFunctions10_6(self):
         self.assertArgIsBlock(CFRunLoopPerformBlock, 2, b'v')

File pyobjc-framework-Cocoa/PyObjCTest/test_cfsocket.py

 import CoreFoundation
 import sys
 
+def onTheNetwork():
+    try:
+        socket.gethostbyname('www.apple.com')
+
+    except socket.gaierror:
+        return False
+
+    return True
+
 
 class TestSocket (TestCase):
     def testTypes(self):
         CFSocketSetDefaultNameRegistryPortNumber(p1)
 
 
+    @onlyIf(onTheNetwork(), "cannot test without internet connection")
     def testSocketFunctions(self):
         data = {}
         state = []
         self.assertNotHasAttr(CoreFoundation, 'CFSocketRegisterSocketSignature')
         self.assertNotHasAttr(CoreFoundation, 'CFSocketRegisterValue')
         self.assertNotHasAttr(CoreFoundation, 'CFSocketUnregister')
+
 if __name__ == "__main__":
     main()

File pyobjc-framework-Cocoa/PyObjCTest/test_cfstream.py

 from CoreFoundation import *
 import errno, time, os, socket, sys
 
+from test_cfsocket import onTheNetwork
+
 
 class TestStream (TestCase):
     def testTypes(self):
 
         del readStream, writeStream
 
+    @onlyIf(onTheNetwork)
     def testSockets(self):
         sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
         sd.connect(('www.apple.com', 80))

File pyobjc-framework-Cocoa/PyObjCTest/test_cfusernotification.py

         id = CFUserNotificationGetTypeID()
         self.assertIsInstance(id, (int, long))
     def testCreation(self):
+        runloop_mode = kCFRunLoopDefaultMode
+        runloop_mode = u"pyobjctest.cfusernotificaton"
+
         rl = CFRunLoopGetCurrent()
 
         infoDict = {
         self.assertArgIsFunction(CFUserNotificationCreateRunLoopSource, 2, b'v^{__CFUserNotification=}' + objc._C_NSInteger, True)
         rls = CFUserNotificationCreateRunLoopSource(None, ref, callout, 1)
         self.assertIsInstance(rls, CFRunLoopSourceRef)
-        CFRunLoopAddSource(rl, rls, kCFRunLoopDefaultMode)
-        CFRunLoopRunInMode(kCFRunLoopDefaultMode, 2.0, True)
+        CFRunLoopAddSource(rl, rls, runloop_mode)
+        CFRunLoopRunInMode(runloop_mode, 2.0, True)
 
         CFUserNotificationCancel(ref)
-        CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, True)
+        CFRunLoopRunInMode(runloop_mode, 5.0, True)
+        CFRunLoopRemoveSource(rl, rls, runloop_mode)
 
         self.assertEqual(len(values), 1)
         self.assertIs(values[0][0], ref)

File pyobjc-framework-Cocoa/PyObjCTest/test_nsbitmapimagerep.py

         i2 = NSBitmapImageRep.alloc().initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel_(None, width, height, 8, 3, NO, NO, NSDeviceRGBColorSpace, 0, 0)
         self.assert_(i2)
 
+    def testPixelFormat(self):
+        width = 16
+        height = 16
+
+        i1 = NSBitmapImageRep.alloc().initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_(None, width, height, 8, 3, NO, NO, NSDeviceRGBColorSpace, NSAlphaFirstBitmapFormat, 0, 0)
+        self.assertIsInstance(i1, NSBitmapImageRep)
+
+        singlePlane = objc.allocateBuffer(width*height*4)
+        for i in range(0, width*height):
+            si = i * 4
+            singlePlane[si] = 1
+            singlePlane[si+1] = 2
+            singlePlane[si+2] = 3
+            singlePlane[si+3] = 4
+        dataPlanes = (singlePlane, None, None, None, None)
+        # test non-planar, premade buffer
+        i2 = NSBitmapImageRep.alloc().initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_(dataPlanes, width, height, 8, 3, NO, NO, NSDeviceRGBColorSpace, NSAlphaFirstBitmapFormat, 0, 0)
+        self.assertIsInstance(i2, NSBitmapImageRep)
+
+        bitmapData = i2.bitmapData()
+
+        self.assertEqual(len(bitmapData), width * height * 4)
+
     def testImageData(self):
         width = 256
         height = 256
         self.assert_(i1)
 
         singlePlane = objc.allocateBuffer(width*height*3)
-        for i in range(0, 256*256):
+        for i in range(0, width*height):
             si = i * 3
             singlePlane[si] = rPlane[i]
             singlePlane[si+1] = gPlane[i]
             singlePlane[si+2] = bPlane[i]
-
         dataPlanes = (singlePlane, None, None, None, None)
         # test non-planar, premade buffer
         i2 = NSBitmapImageRep.alloc().initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel_(dataPlanes, width, height, 8, 3, NO, NO, NSDeviceRGBColorSpace, 0, 0)
         b[0:len(b)] = bPlane[0:len(bPlane)]
 
         bitmapData = i2.bitmapData()
+
         self.assertEqual(len(bitmapData), len(singlePlane))
-        self.assertEqual(bitmapData, singlePlane)
+        try:
+            memoryview
+        except NameError:
+            self.assertEqual(bitmapData, singlePlane)
+        else:
+            self.assertEquals(bitmapData.tobytes(),
+                singlePlane)
         
         a = array.array('L', [255]*4)
         self.assertArgIsOut(NSBitmapImageRep.getPixel_atX_y_, 0)
         d = i2.getPixel_atX_y_(a, 1, 1)
         self.assertIs(a, d)
+
 class TestBadCreation(TestCase):
 
     # Redirect stderr to /dev/null for the duration of this test, 
         self.assertArgIsOut(NSBitmapImageRep.getCompression_factor_, 0)
         self.assertArgIsOut(NSBitmapImageRep.getCompression_factor_, 1)
 
-        self.fail("- (id)initWithBitmapDataPlanes:(unsigned char **)planes pixelsWide:(NSInteger)width pixelsHigh:(NSInteger)height bitsPerSample:(NSInteger)bps samplesPerPixel:(NSInteger)spp hasAlpha:(BOOL)alpha isPlanar:(BOOL)isPlanar colorSpaceName:(NSString *)colorSpaceName  bitmapFormat:(NSBitmapFormat)bitmapFormat bytesPerRow:(NSInteger)rBytes bitsPerPixel:(NSInteger)pBits;")
-
 
 
 if __name__ == '__main__':

File pyobjc-framework-Cocoa/PyObjCTest/test_nsnull.py

 class TestNSNull (TestCase):
     def testBool(self):
         v = NSNull.null()
-        print bool(v)
         self.assert_(not v)
         self.assert_(v is not None)
 

File pyobjc-framework-Cocoa/setup.py

 for information on how to use these frameworks and PyObjC's documentation
 for general tips and tricks regarding the translation between Python
 and (Objective-)C frameworks
+
+NEWS
+====
+
+2.4
+-----
+
+- Fix wrappers for a number of NSBitmap methods, those got broken while
+  introducing Python 3 support.
+
+- Add wrapper for [NSBitmapImageRep -initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:]
 '''
 from pyobjc_setup import setup, Extension
 import os

File pyobjc-framework-CoreData/PyObjCTest/test_managedkvo.py

 
 class CoreDataTestObject (CoreData.NSManagedObject):
     def __getattr__(self, k):
-        print "get", k
         raise AttributeError(k)
 
     def __setattr__(self, k, v):
 
     def testPythonicAttribute(self):
         managedObject = CoreData.NSManagedObject.alloc().initWithEntity_insertIntoManagedObjectContext_(self.entity, self.managedObjectContext)
-        print managedObject
 
         testValue = u'Ducks have webbed feet'
         self.assertRaises(AttributeError, setattr, managedObject, 'attributeWithoutModel', testValue)
         self.assertEquals(testValue, managedObject._.testAttribute)
 
     def testPythonicAttribute(self):
-        self.fail("research recursion problem")
+        #self.fail("research recursion problem")
         managedObject = CoreDataTestObject.alloc().initWithEntity_insertIntoManagedObjectContext_(self.entity, self.managedObjectContext)
         self.assert_(isinstance(managedObject, CoreDataTestObject))
 

File pyobjc-framework-CoreText/Doc/api-notes-CoreText.txt

 
   Use ``CTParagraphStyleGetTabStops`` to fetch the tabstops from a style object, using
   ``CTParagraphStyleGetValueSpecifieker`` is not supported with key ``kCTParagraphStyleSpecifierTabStops``.
+
+* ``CTRunGetAdvancesPtr`` is not supported, use ``CTRunGetAdvances`` instead.

File pyobjc-framework-CoreText/Lib/CoreText/PyObjC.bridgesupport

     <arg type='l' type64='l' />
     <arg type='d' />
   </function>
+  <function name='CTFramesetterSuggestFrameSizeWithConstraints'>
+    <retval type='{_NSSize=ff}' type64='{CGSize=dd}' />
+    <arg type='^{__CTTypesetter=}' />
+    <arg type='{_CFRange=ll}' type64='{_CFRange=ll}' />
+    <arg type='@' />
+    <arg type='{_NSSize=ff}' type64='{CGSize=dd}' />
+    <arg type='^{_CFRange=ll}' type64='^{_CFRange=ll}' type_modifier='o' />
+  </function>
+  <function name='CTRunGetAdvances'>
+    <retval type='v' />
+    <arg type='^{__CTRun=}' />
+    <arg type='{_CFRange=ll}' type64='{_CFRange=ll}' />
+    <arg type='^{_NSSize=ff}' type64='^{CGSize=dd}' type_modifier='o' c_array_length_in_arg='1' />
+  </function>
 </signatures>
 

File pyobjc-framework-CoreText/PyObjCTest/test_ctframesetter.py

 from PyObjCTools.TestSupport import *
 from CoreText import *
 
+try:
+    from Quartz import CGSize
+except ImportError:
+    CGSize = None, None
+
+
 class TestCTFramesetter (TestCase):
 
     def testTypes(self):
         self.assertIsInstance(v, CTTypesetterRef)
 
     @min_os_level('10.5')
+    @onlyIf(CGSize is not None, "CoreGraphics not available")
     def testMethods10_5(self):
-        self.fail('CTFramesetterSuggestFrameSizeWithConstraints')
+        #self.fail('CTFramesetterSuggestFrameSizeWithConstraints')
+        setter = CTFramesetterCreateWithAttributedString(
+                    CFAttributedStringCreate(None, u"hello", None))
+        self.assertIsInstance(setter, CTFramesetterRef)
+
+        self.assertArgIsOut(CTFramesetterSuggestFrameSizeWithConstraints, 4)
+
+        r = CTFramesetterSuggestFrameSizeWithConstraints(
+                setter, CFRange(0, 2), None, CGSize(100, 500),
+                None)
+        self.assertIsInstance(r, tuple)
+        self.assertEquals(len(r), 2)
+
+        size, range = r
+
+        self.assertIsInstance(size, CGSize)
+        self.assertIsInstance(range, CFRange)
+
 
 
 if __name__ == "__main__":

File pyobjc-framework-CoreText/PyObjCTest/test_ctglyphinfo.py

         self.assertIsInstance(v, CTGlyphInfoRef)
 
         self.assertResultIsCFRetained(CTGlyphInfoCreateWithCharacterIdentifier)
-        v = CTGlyphInfoCreateWithCharacterIdentifier(3254, kCTIdentityMappingCharacterCollection, "(c)")
+
+        for collection in (kCTIdentityMappingCharacterCollection, kCTAdobeCNS1CharacterCollection,
+                kCTAdobeGB1CharacterCollection, kCTAdobeJapan1CharacterCollection, 
+                kCTAdobeJapan2CharacterCollection, kCTAdobeKorea1CharacterCollection):
+            v = CTGlyphInfoCreateWithCharacterIdentifier(3254, collection, "(c)")
+            if v is not None:
+                break
         self.assertIsInstance(v, CTGlyphInfoRef)
 
         v = CTGlyphInfoGetGlyphName(info)

File pyobjc-framework-CoreText/PyObjCTest/test_ctrun.py

         self.assertEqual(kCTRunStatusHasNonIdentityMatrix, (1 << 2))
 
     def testFunctions(self):
-        return
         self.assertIsInstance(CTRunGetTypeID(), (int, long))
 
         line = CTLineCreateWithAttributedString(
 
     @min_os_level('10.5')
     def testFunctions10_5(self):
-        self.fail('CTRunGetAdvancesPtr')
-        self.fail('CTRunGetAdvances')
+        self.assertArgIsOut(CTRunGetAdvances, 2)
+        self.assertArgSizeInArg(CTRunGetAdvances, 2, 1)
+
+        line = CTLineCreateWithAttributedString(
+                CFAttributedStringCreate(None, u"hello world", None))
+        self.assertIsInstance(line, CTLineRef)
+
+        run = CTLineGetGlyphRuns(line)[0]
+        self.assertIsInstance(run, CTRunRef)
+
+        r = CTRunGetAdvances(run, CFRange(1, 3), None)
+        self.assertIsInstance(r, (list, tuple))
+        self.assertEquals(len(r), 3)
+        for i in xrange(3):
+            self.assertIsInstance(r[i], CGSize)
+
+
+        try:
+            CTRunGetAdvancesPtr
+        except NameError:
+            pass
+        else:
+            self.fail("CTRunGetAdvancesPtr is defined")
 
 
 if __name__ == "__main__":

File pyobjc-framework-CoreText/setup.py

 for information on how to use this framework and PyObjC's documentation
 for general tips and tricks regarding the translation between Python
 and (Objective-)C frameworks
+
+NEWS
+====
+
+2.4
+---
+
+* The wrappers now cover all useful functionality (see the documentation
+  for the exceptions)
 '''
 from pyobjc_setup import setup, Extension