Skip to content

Commit

Permalink
Add Python 2.6 capsule compatibility header
Browse files Browse the repository at this point in the history
The core_types extension module is not compatible with Python 2.6 due
to the use of capsules, which were introduced in 2.7.

As a workaround a compatibility header that redefines PyCapsule C API
calls in terms of PyCObject is introduced.

See also http://docs.python.org/2/howto/cporting.html
  • Loading branch information
kynan committed Oct 15, 2013
1 parent 2b75f69 commit c2415d3
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 0 deletions.
134 changes: 134 additions & 0 deletions python/firedrake/capsulethunk.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#ifndef __CAPSULETHUNK_H
#define __CAPSULETHUNK_H

#if ( (PY_VERSION_HEX < 0x02070000) \
|| ((PY_VERSION_HEX >= 0x03000000) \
&& (PY_VERSION_HEX < 0x03010000)) )

#define __PyCapsule_GetField(capsule, field, default_value) \
( PyCapsule_CheckExact(capsule) \
? (((PyCObject *)capsule)->field) \
: (default_value) \
) \

#define __PyCapsule_SetField(capsule, field, value) \
( PyCapsule_CheckExact(capsule) \
? (((PyCObject *)capsule)->field = value), 1 \
: 0 \
) \


#define PyCapsule_Type PyCObject_Type

#define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule))
#define PyCapsule_IsValid(capsule, name) (PyCObject_Check(capsule))


#define PyCapsule_New(pointer, name, destructor) \
(PyCObject_FromVoidPtr(pointer, destructor))


#define PyCapsule_GetPointer(capsule, name) \
(PyCObject_AsVoidPtr(capsule))

/* Don't call PyCObject_SetPointer here, it fails if there's a destructor */
#define PyCapsule_SetPointer(capsule, pointer) \
__PyCapsule_SetField(capsule, cobject, pointer)


#define PyCapsule_GetDestructor(capsule) \
__PyCapsule_GetField(capsule, destructor)

#define PyCapsule_SetDestructor(capsule, dtor) \
__PyCapsule_SetField(capsule, destructor, dtor)


/*
* Sorry, there's simply no place
* to store a Capsule "name" in a CObject.
*/
#define PyCapsule_GetName(capsule) NULL

static int
PyCapsule_SetName(PyObject *capsule, const char *unused)
{
unused = unused;
PyErr_SetString(PyExc_NotImplementedError,
"can't use PyCapsule_SetName with CObjects");
return 1;
}



#define PyCapsule_GetContext(capsule) \
__PyCapsule_GetField(capsule, descr)

#define PyCapsule_SetContext(capsule, context) \
__PyCapsule_SetField(capsule, descr, context)


static void *
PyCapsule_Import(const char *name, int no_block)
{
PyObject *object = NULL;
void *return_value = NULL;
char *trace;
size_t name_length = (strlen(name) + 1) * sizeof(char);
char *name_dup = (char *)PyMem_MALLOC(name_length);

if (!name_dup) {
return NULL;
}

memcpy(name_dup, name, name_length);

trace = name_dup;
while (trace) {
char *dot = strchr(trace, '.');
if (dot) {
*dot++ = '\0';
}

if (object == NULL) {
if (no_block) {
object = PyImport_ImportModuleNoBlock(trace);
} else {
object = PyImport_ImportModule(trace);
if (!object) {
PyErr_Format(PyExc_ImportError,
"PyCapsule_Import could not "
"import module \"%s\"", trace);
}
}
} else {
PyObject *object2 = PyObject_GetAttrString(object, trace);
Py_DECREF(object);
object = object2;
}
if (!object) {
goto EXIT;
}

trace = dot;
}

if (PyCObject_Check(object)) {
PyCObject *cobject = (PyCObject *)object;
return_value = cobject->cobject;
} else {
PyErr_Format(PyExc_AttributeError,
"PyCapsule_Import \"%s\" is not valid",
name);
}

EXIT:
Py_XDECREF(object);
if (name_dup) {
PyMem_FREE(name_dup);
}
return return_value;
}

#endif /* #if PY_VERSION_HEX < 0x02070000 */

#endif /* __CAPSULETHUNK_H */
2 changes: 2 additions & 0 deletions python/firedrake/core_types.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ cimport numpy as np
cimport cpython as py
cimport fluidity_types as ft

cdef extern from "capsulethunk.h": pass

np.import_array()

cdef char *_function_space_name = "function_space"
Expand Down

0 comments on commit c2415d3

Please sign in to comment.