tag 481506 patch Hi,
apologies for lobbying for my pet peeves to be fixed in lenny, but the attached python script (taking from upstream python-cairo 1.6.4[1], needing python-pygame and python-cairo to be installed) works with python 2.4 as is but not with the default python (2.5). Applying the attached diff improves the situation making this also work with python 2.5. Some gory details below. While the bug severity is set to "normal", the error message is somewhat opaque and searching the internet only reveals some "maybe we should fix this" comment, so the Debian user's experience might be improved by eliminating the need for the search. If this is interesting enough for people to upload and later unblock... And here the promised gory details: - The signature changes (insofar as they are changes) to Py_ssize_t are from the python 2.5 documentation. For python 2.4 they are actually no changes thanks to the cairo-private.h compatibility typedefs that seem to be based on PEP 353[2]. - python-pygame uses PyObject_AsCharBuffer from the abstract buffer protocol to get hold of the image buffer. This function seems to exist since Python 1.6 (certainly does in 2.4), but only python 2.5 changes is to actually use the charbufferproc that is now missing in python-cairo. - I don't know why pycairo upstream does not seem to have implemented this despite adding tests that fail on python 2.5. Maybe they still use python 2.4 only? Kind regards T. 1. http://webcvs.cairographics.org/pycairo/test/pygame-test1.py 2. http://www.python.org/dev/peps/pep-0353/ -- Thomas Viehmann, http://thomas.viehmann.net/
#!/usr/bin/env python """demonstrate pycairo and pygame method1: use a pycairo and pygame directly """ import array import math import sys import cairo import pygame def draw(surface): x,y, radius = (250,250, 200) ctx = cairo.Context(surface) ctx.set_line_width(15) ctx.arc(x, y, radius, 0, 2.0 * math.pi) ctx.set_source_rgb(0.8, 0.8, 0.8) ctx.fill_preserve() ctx.set_source_rgb(1, 1, 1) ctx.stroke() def input(events): for event in events: if event.type == pygame.QUIT: sys.exit(0) else: print event Width, Height = 512, 512 surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, Width, Height) pygame.init() window = pygame.display.set_mode( (Width,Height) ) screen = pygame.display.get_surface() draw(surface) #Create PyGame surface from Cairo Surface buf = surface.get_data() image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",) #Tranfer to Screen screen.blit(image, (0,0)) pygame.display.flip() while True: input(pygame.event.get()) """ with pycairo 1.4.12 and pygame 1.7.1 you get the error message: Traceback (most recent call last): File "./pygame-test1.py", line 42, in <module> image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",) TypeError: char buffer type not available This is because with buf = surface.get_data() pycairo provides a binary image buffer, whereas with image = pygame.image.frombuffer(buf,(Width,Height),"ARGB",) pygame is expecting a text-based character buffer! """
diff -u pycairo-1.4.12/debian/changelog pycairo-1.4.12/debian/changelog --- pycairo-1.4.12/debian/changelog +++ pycairo-1.4.12/debian/changelog @@ -1,3 +1,12 @@ +pycairo (1.4.12-1.2) unstable; urgency=low + + * Non-maintainer upload. + * Python 2.5 compatibility of Image buffer interface. + (needed e.g. for interaction with python-pygame). + Closes: #481506 + + -- Thomas Viehmann <t...@beamnet.de> Tue, 13 Jan 2009 22:51:49 +0100 + pycairo (1.4.12-1.1) unstable; urgency=low * NMU. only in patch2: unchanged: --- pycairo-1.4.12.orig/cairo/pycairo-surface.c +++ pycairo-1.4.12/cairo/pycairo-surface.c @@ -504,8 +504,8 @@ /* Buffer interface functions, used by ImageSurface.get_data() */ -static int -image_surface_buffer_getreadbuf (PycairoImageSurface *o, int segment, +static Py_ssize_t +image_surface_buffer_getreadbuf (PycairoImageSurface *o, Py_ssize_t segment, const void **ptr) { cairo_surface_t *surface = o->surface; @@ -522,8 +522,8 @@ return height * stride; } -static int -image_surface_buffer_getwritebuf (PycairoImageSurface *o, int segment, +static Py_ssize_t +image_surface_buffer_getwritebuf (PycairoImageSurface *o, Py_ssize_t segment, const void **ptr) { cairo_surface_t *surface = o->surface; @@ -540,25 +540,43 @@ return height * stride; } -static int -image_surface_buffer_getsegcount (PycairoImageSurface *o, int *lenp) +static Py_ssize_t +image_surface_buffer_getsegcount (PycairoImageSurface *o, Py_ssize_t *lenp) { if (lenp) { /* report the sum of the sizes (in bytes) of all segments */ cairo_surface_t *surface = o->surface; int height = cairo_image_surface_get_height (surface); int stride = cairo_image_surface_get_stride (surface); - *lenp = height * stride; + *lenp = (Py_ssize_t) height * stride; } return 1; /* surface data is all in one segment */ } +static Py_ssize_t +image_surface_buffer_getcharbuf (PycairoImageSurface *o, Py_ssize_t segment, + const char **ptr) +{ + cairo_surface_t *surface = o->surface; + int height, stride; + + if (segment != 0) { + PyErr_SetString(PyExc_SystemError, + "accessing non-existent ImageSurface segment"); + return -1; + } + height = cairo_image_surface_get_height (surface); + stride = cairo_image_surface_get_stride (surface); + *ptr = (char *) cairo_image_surface_get_data (surface); + return height * stride; +} + /* See Python C API Manual 10.7 */ static PyBufferProcs image_surface_as_buffer = { (readbufferproc) image_surface_buffer_getreadbuf, (writebufferproc)image_surface_buffer_getwritebuf, (segcountproc) image_surface_buffer_getsegcount, - (charbufferproc) NULL, + (charbufferproc) image_surface_buffer_getcharbuf, }; static PyMethodDef image_surface_methods[] = {