Date: Sun, 25 Jul 2021 16:17:19 GMT From: Jan Beich <jbeich@FreeBSD.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org Subject: git: bf17672f5058 - main - graphics/py-cairo: unbreak with python310 Message-ID: <202107251617.16PGHJTb081723@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by jbeich: URL: https://cgit.FreeBSD.org/ports/commit/?id=bf17672f50580a768f536ca3c5b243324e2cd64a commit bf17672f50580a768f536ca3c5b243324e2cd64a Author: Jan Beich <jbeich@FreeBSD.org> AuthorDate: 2021-07-25 15:17:51 +0000 Commit: Jan Beich <jbeich@FreeBSD.org> CommitDate: 2021-07-25 16:17:05 +0000 graphics/py-cairo: unbreak with python310 >>> import cairo Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.10/site-packages/cairo/__init__.py", line 1, in <module> from ._cairo import * # noqa: F401,F403 ImportError: /usr/local/lib/python3.10/site-packages/cairo/_cairo.cpython-310.so: Undefined symbol "PyObject_AsReadBuffer" ImportError: /usr/local/lib/python3.10/site-packages/cairo/_cairo.cpython-310.so: Undefined symbol "PyObject_AsWriteBuffer" --- graphics/py-cairo/Makefile | 2 +- graphics/py-cairo/files/patch-cairo_surface.c | 215 ++++++++++++++++++++++++++ 2 files changed, 216 insertions(+), 1 deletion(-) diff --git a/graphics/py-cairo/Makefile b/graphics/py-cairo/Makefile index 3afb3bd7cd16..3570aa42fc6d 100644 --- a/graphics/py-cairo/Makefile +++ b/graphics/py-cairo/Makefile @@ -2,7 +2,7 @@ PORTNAME= cairo PORTVERSION= 1.18.1 -PORTREVISION= 1 +PORTREVISION= 2 PORTEPOCH= 1 CATEGORIES= graphics python MASTER_SITES= https://github.com/pygobject/pycairo/releases/download/v${PORTVERSION}/ diff --git a/graphics/py-cairo/files/patch-cairo_surface.c b/graphics/py-cairo/files/patch-cairo_surface.c new file mode 100644 index 000000000000..b4ab64c6fe21 --- /dev/null +++ b/graphics/py-cairo/files/patch-cairo_surface.c @@ -0,0 +1,215 @@ +https://github.com/pygobject/pycairo/commit/0f8cdc058239 +https://github.com/pygobject/pycairo/commit/4c5377787624 +https://github.com/pygobject/pycairo/commit/590bcd2ecc9c + +--- cairo/surface.c.orig 2018-11-03 09:30:34 UTC ++++ cairo/surface.c +@@ -142,6 +142,7 @@ _write_func (void *closure, const unsigned char *data, + + static const cairo_user_data_key_t surface_base_object_key; + static const cairo_user_data_key_t surface_is_mapped_image; ++static const cairo_user_data_key_t surface_buffer_view_key; + + static void + surface_dealloc (PycairoSurface *o) { +@@ -439,28 +440,30 @@ _destroy_mime_user_data_func (PyObject *user_data) { + static void + _destroy_mime_data_func (PyObject *user_data) { + cairo_surface_t *surface; ++ Py_buffer *view; + PyObject *mime_intern; + + PyGILState_STATE gstate = PyGILState_Ensure(); + + /* Remove the user data holding the source object */ + surface = PyCapsule_GetPointer(PyTuple_GET_ITEM(user_data, 0), NULL); +- mime_intern = PyTuple_GET_ITEM(user_data, 2); ++ view = PyCapsule_GetPointer(PyTuple_GET_ITEM(user_data, 1), NULL); ++ mime_intern = PyTuple_GET_ITEM(user_data, 3); + cairo_surface_set_user_data( + surface, (cairo_user_data_key_t *)mime_intern, NULL, NULL); + + /* Destroy the user data */ +- _destroy_mime_user_data_func(user_data); ++ PyBuffer_Release (view); ++ PyMem_Free (view); ++ Py_DECREF(user_data); + + PyGILState_Release(gstate); + } + + static PyObject * + surface_set_mime_data (PycairoSurface *o, PyObject *args) { +- PyObject *obj, *user_data, *mime_intern, *capsule; +- const unsigned char *buffer; ++ PyObject *obj, *user_data, *mime_intern, *surface_capsule, *view_capsule; + const char *mime_type; +- Py_ssize_t buffer_len; + int res; + cairo_status_t status; + +@@ -475,38 +478,58 @@ surface_set_mime_data (PycairoSurface *o, PyObject *ar + Py_RETURN_NONE; + } + +-PYCAIRO_BEGIN_IGNORE_DEPRECATED +- res = PyObject_AsReadBuffer (obj, (const void **)&buffer, &buffer_len); +-PYCAIRO_END_IGNORE_DEPRECATED +- if (res == -1) ++ Py_buffer *view = PyMem_Malloc (sizeof (Py_buffer)); ++ if (view == NULL) { ++ PyErr_NoMemory (); + return NULL; ++ } + ++ res = PyObject_GetBuffer (obj, view, PyBUF_READ); ++ if (res == -1) { ++ PyMem_Free (view); ++ return NULL; ++ } ++ + /* We use the interned mime type string as user data key and store the + * passed in object with it. This allows us to return the same object in + * surface_get_mime_data(). + */ + mime_intern = PYCAIRO_PyUnicode_InternFromString(mime_type); +- capsule = PyCapsule_New(o->surface, NULL, NULL); +- user_data = Py_BuildValue("(NOO)", capsule, obj, mime_intern); +- if (user_data == NULL) ++ surface_capsule = PyCapsule_New(o->surface, NULL, NULL); ++ view_capsule = PyCapsule_New(view, NULL, NULL); ++ user_data = Py_BuildValue("(NNOO)", surface_capsule, view_capsule, obj, mime_intern); ++ if (user_data == NULL) { ++ PyBuffer_Release (view); ++ PyMem_Free (view); + return NULL; ++ } + + status = cairo_surface_set_user_data( + o->surface, (cairo_user_data_key_t *)mime_intern, user_data, + (cairo_destroy_func_t)_destroy_mime_user_data_func); +- if (status != CAIRO_STATUS_SUCCESS) ++ ++ if (status != CAIRO_STATUS_SUCCESS) { ++ PyBuffer_Release (view); ++ PyMem_Free (view); + Py_DECREF(user_data); +- RETURN_NULL_IF_CAIRO_ERROR(status); ++ Pycairo_Check_Status (status); ++ return NULL; ++ } + ++ Py_INCREF(user_data); + status = cairo_surface_set_mime_data ( +- o->surface, mime_type, buffer, (unsigned long)buffer_len, ++ o->surface, mime_type, view->buf, (unsigned long)view->len, + (cairo_destroy_func_t)_destroy_mime_data_func, user_data); ++ + if (status != CAIRO_STATUS_SUCCESS) { + cairo_surface_set_user_data( + o->surface, (cairo_user_data_key_t *)mime_intern, NULL, NULL); ++ PyBuffer_Release (view); ++ PyMem_Free (view); ++ Py_DECREF(user_data); ++ Pycairo_Check_Status (status); ++ return NULL; + } +- RETURN_NULL_IF_CAIRO_ERROR(status); +- Py_INCREF(user_data); + + Py_RETURN_NONE; + } +@@ -534,7 +557,7 @@ surface_get_mime_data (PycairoSurface *o, PyObject *ar + /* In case the mime data wasn't set through the Python API just copy it */ + return Py_BuildValue(PYCAIRO_DATA_FORMAT "#", buffer, buffer_len); + } else { +- obj = PyTuple_GET_ITEM(user_data, 1); ++ obj = PyTuple_GET_ITEM(user_data, 2); + Py_INCREF(obj); + return obj; + } +@@ -804,14 +827,22 @@ image_surface_new (PyTypeObject *type, PyObject *args, + NULL); + } + ++static void ++_release_buffer_destroy_func (void *user_data) { ++ Py_buffer *view = (Py_buffer *)user_data; ++ PyGILState_STATE gstate = PyGILState_Ensure(); ++ PyBuffer_Release (view); ++ PyMem_Free (view); ++ PyGILState_Release(gstate); ++} ++ + /* METH_CLASS */ + static PyObject * + image_surface_create_for_data (PyTypeObject *type, PyObject *args) { + cairo_surface_t *surface; + cairo_format_t format; +- unsigned char *buffer; ++ cairo_status_t status; + int width, height, stride = -1, res, format_arg; +- Py_ssize_t buffer_len; + PyObject *obj; + + if (!PyArg_ParseTuple (args, "Oiii|i:ImageSurface.create_for_data", +@@ -820,12 +851,6 @@ image_surface_create_for_data (PyTypeObject *type, PyO + + format = (cairo_format_t)format_arg; + +-PYCAIRO_BEGIN_IGNORE_DEPRECATED +- res = PyObject_AsWriteBuffer (obj, (void **)&buffer, &buffer_len); +-PYCAIRO_END_IGNORE_DEPRECATED +- if (res == -1) +- return NULL; +- + if (width <= 0) { + PyErr_SetString(PyExc_ValueError, "width must be positive"); + return NULL; +@@ -843,15 +868,42 @@ PYCAIRO_END_IGNORE_DEPRECATED + return NULL; + } + } +- if (height * stride > buffer_len) { ++ ++ Py_buffer *view = PyMem_Malloc (sizeof (Py_buffer)); ++ if (view == NULL) { ++ PyErr_NoMemory (); ++ return NULL; ++ } ++ ++ res = PyObject_GetBuffer (obj, view, PyBUF_WRITABLE); ++ if (res == -1) { ++ PyMem_Free (view); ++ return NULL; ++ } ++ ++ if (height * stride > view->len) { ++ PyBuffer_Release (view); ++ PyMem_Free (view); + PyErr_SetString(PyExc_TypeError, "buffer is not long enough"); + return NULL; + } ++ + Py_BEGIN_ALLOW_THREADS; +- surface = cairo_image_surface_create_for_data (buffer, format, width, +- height, stride); ++ surface = cairo_image_surface_create_for_data (view->buf, format, width, ++ height, stride); + Py_END_ALLOW_THREADS; +- return _surface_create_with_object(surface, obj); ++ ++ status = cairo_surface_set_user_data( ++ surface, &surface_buffer_view_key, view, ++ (cairo_destroy_func_t)_release_buffer_destroy_func); ++ if (Pycairo_Check_Status (status)) { ++ cairo_surface_destroy (surface); ++ PyBuffer_Release (view); ++ PyMem_Free (view); ++ return NULL; ++ } ++ ++ return PycairoSurface_FromSurface(surface, NULL); + } + +
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202107251617.16PGHJTb081723>